Navigator.sendBeacon() to pass header information

后端 未结 6 1910
Happy的楠姐
Happy的楠姐 2020-12-06 00:51

I am using navigator for communicating with the server , but problem is that we need to pass some header information as there is filter which recognise the request is from t

相关标签:
6条回答
  • 2020-12-06 01:00

    Because the method sendBeacon(..) does not allow headers manipulation, I added them into the form as normal fields:

        const formData = new FormData();
        formData.append('authorization', myAuthService.getCachedToken());
        navigator.sendBeacon(myURL, formData);
    

    Then on the host side I added a simple Middleware class (.Net) which catches POST requests without headers and copies them from the body:

        public class AuthMiddleware
        {
            ...
            ...
            public async Task Invoke(HttpContext context)
            {
                string authHeader = context.Request.Headers["Authorization"];
                if (authHeader == null && context.Request.Method=="POST")
                {
                    context.Request.Headers["Authorization"] = string.Format("Bearer {0}",
                        context.Request.Form["authorization"].ToString());
                }
    
                await _next.Invoke(context);
            }
        }
    
    0 讨论(0)
  • 2020-12-06 01:04

    As written in the Processing Model of sendBeacon :

    Extract object's byte stream (transmittedData) and content type (contentType).

    How extraction is performed is described here

    What I've gathered is that the content type of the transmitted data is extracted, and it is set as the Content-Type of the HTTP request.

    1) If a Blob object is sent, the Content-Type becomes the Blob's type.

    2) If a FormData object is sent, the Content-Type becomes multipart/form-data

    3) If a URLSearchParams object is sent, the Content-Type becomes application/x-www-form-urlencoded

    4) If a normal string is sent, the Content-Type becomes text/plain

    Javascript code to implement different objects can be found here

    0 讨论(0)
  • 2020-12-06 01:06

    If you're using Chrome and you're trying to set the content-type header, you'll probably have some issues due to security restrictions :

    Uncaught DOMException: Failed to execute 'sendBeacon' on 'Navigator': sendBeacon() with a Blob whose type is not any of the CORS-safelisted values for the Content-Type request header is disabled temporarily. See http://crbug.com/490015 for details.
    

    See this thread

    0 讨论(0)
  • 2020-12-06 01:17

    Posting as an answer as I'm not allowed to post a comment under the answer:

    For Chrome, issue with navigator.sendBeacon sending Blob for with non CORS-safelisted types was fixed in Chrome version 81 so this should be safe to use now. https://bugs.chromium.org/p/chromium/issues/detail?id=724929

    For IE, an alternative in unload event is to use synchronous ajax request, as IE doesn't support sendBeacon but supports synchronous ajax call in my case.

    0 讨论(0)
  • 2020-12-06 01:21

    @Vipul Panth has helpful information, but I wanted to provide some more complete details.

    First, note that navigator.sendBeacon is not supported in all browsers. See more detail about this function as well as currently supported browsers at the MDN documentation.

    You do indeed create a blob to provide headers. Here is an example:

    window.onunload = function () {
      let body = {
        id,
        email
      };
      let headers = {
        type: 'application/json'
      };
      let blob = new Blob([JSON.stringify(body)], headers);
      navigator.sendBeacon('url', blob);
    });
    

    navigator.sendBeacon will send a POST request with the Content-Type request header set to whatever is in headers.type. This seems to be the only header you can set in a beacon though, per W3C:

    The sendBeacon method does not provide ability to customize the request method, provide custom request headers, or change other processing properties of the request and response. Applications that require non-default settings for such requests should use the [FETCH] API with keepalive flag set to true.

    I was able to observe some of how this worked through this Chromium bug report.

    0 讨论(0)
  • 2020-12-06 01:21

    After searching for an answer for this question I found out that for passing header with navigator we need to pass a blob object.

    For example

    var headers = {type: 'application/json'};
    var blob = new Blob(request, headers);
    navigator.sendBeacon('url/to/send', blob);
    
    0 讨论(0)
提交回复
热议问题