Search code examples
azureazure-web-app-servicehttp2

HTTP2 requests with Azure web app and web api


We recently enabled HTTP2 traffic between our azure web site and our web api. This was enabled via a switch in the azure portal. The first request from the web app to the web api fails with : (Failed) net::ERR_SPDY_PROTOCOL_ERROR

And doesnt look like the request ever makes it to the api. We have tried upgrading both apps to .NET 4.6.1, assuming that the new HTTP2 protocol wouldnt be supported with older versions. I am struggling to find anything of use in dev tools in chrome, or using the advanced trace tools in chrome. Here is the error that we see when inspecting the verbose HTTP2 session event trace of the request to the api using the advanced Chrome network tool (chrome://net-internals/#events):

t=314214 [st=  0] +HTTP2_SESSION  [dt=?]
                   --> host = "autoservice.compareunittest.com:443"
                   --> proxy = "DIRECT"
t=314214 [st=  0]    HTTP2_SESSION_INITIALIZED
                     --> protocol = "h2"
                     --> source_dependency = 129205 (SOCKET)
t=314214 [st=  0]    HTTP2_SESSION_SEND_SETTINGS
                     --> settings = ["[id:1 (SETTINGS_HEADER_TABLE_SIZE) value:65536]","[id:3 (SETTINGS_MAX_CONCURRENT_STREAMS) value:1000]","[id:4 (SETTINGS_INITIAL_WINDOW_SIZE) value:6291456]"]
t=314214 [st=  0]    HTTP2_SESSION_UPDATE_RECV_WINDOW
                     --> delta = 15663105
                     --> window_size = 15728640
t=314214 [st=  0]    HTTP2_SESSION_SEND_WINDOW_UPDATE
                     --> delta = 15663105
                     --> stream_id = 0
t=314214 [st=  0]    HTTP2_SESSION_SEND_HEADERS
                     --> exclusive = true
                     --> fin = true
                     --> has_priority = true
                     --> :method: OPTIONS
                         :authority: autoservice.compareunittest.com
                         :scheme: https
                         :path: /api/mi/abtestlogbatch
                         access-control-request-method: POST
                         origin: https://motor.compareunittest.com
                         user-agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36
                         access-control-request-headers: __requestverificationtoken,authorization,content-type,correlationid
                         accept: */*
                         accept-encoding: gzip, deflate, br
                         accept-language: en-GB,en-US;q=0.9,en;q=0.8
                     --> parent_stream_id = 0
                     --> source_dependency = 129202 (HTTP_STREAM_JOB)
                     --> stream_id = 1
                     --> weight = 220
t=314424 [st=210]    HTTP2_SESSION_RECV_SETTINGS
t=314424 [st=210]    HTTP2_SESSION_SEND_SETTINGS_ACK
t=314424 [st=210]    HTTP2_SESSION_RECV_SETTING
                     --> id = "3 (SETTINGS_MAX_CONCURRENT_STREAMS)"
                     --> value = 100
t=314424 [st=210]    HTTP2_SESSION_UPDATE_STREAMS_SEND_WINDOW_SIZE
                     --> delta_window_size = 983041
t=314424 [st=210]    HTTP2_SESSION_RECV_SETTING
                     --> id = "4 (SETTINGS_INITIAL_WINDOW_SIZE)"
                     --> value = 1048576
t=314424 [st=210]    HTTP2_SESSION_RECV_WINDOW_UPDATE
                     --> delta = 983041
                     --> stream_id = 0
t=314424 [st=210]    HTTP2_SESSION_UPDATE_SEND_WINDOW
                     --> delta = 983041
                     --> window_size = 1048576
t=314424 [st=210]    HTTP2_SESSION_RECV_SETTINGS_ACK
t=314424 [st=210]    HTTP2_SESSION_RECV_HEADERS
                     --> fin = false
                     --> :status: 200
                         allow: OPTIONS, TRACE, GET, HEAD, POST
                         server: Microsoft-IIS/10.0
                         public: OPTIONS, TRACE, GET, HEAD, POST
                         x-powered-by: ASP.NET
                         access-control-allow-origin: *
                         access-control-allow-headers: Origin, X-Requested-With, Content-Type, Accept, Authorization, Cache-Control, __RequestVerificationToken, CorrelationId
                         x-frame-options: SAMEORIGIN
                         date: Thu, 03 May 2018 14:48:24 GMT
                         content-length: 0
                     --> stream_id = 1
t=314424 [st=210]    HTTP2_SESSION_RECV_DATA
                     --> fin = true
                     --> size = 0
                     --> stream_id = 1
t=314535 [st=321]    HTTP2_SESSION_SEND_HEADERS
                     --> exclusive = true
                     --> fin = false
                     --> has_priority = true
                     --> :method: POST
                         :authority: autoservice.compareunittest.com
                         :scheme: https
                         :path: /api/mi/abtestlogbatch
                         content-length: 311
                         correlationid: 72b3a477-1129-4ca4-a373-3bd6cdc2c5b0
                         origin: https://motor.compareunittest.com
                         authorization: 48iFi3wa47u4yT46TfwRj3dcC651N275Cn=
                         content-type: application/json;charset=UTF-8
                         accept: application/json, text/plain, */*
                         user-agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36
                         __requestverificationtoken: GmI53U-AOKgq8RZ92Qf59kazIktqpOEPVZ4LzF_uL562FYPOz2ylxk94VYG3dJwZm-ZwhrfMOYjvfPWovI37OJ4mI3yDG6Do2DaBGY0HkC41:kE5Uxfh3fNgktZIhW1XG84nflggp3EULxtJbu_NCHiBwPxrOMeOAxiI7CoBWMGH3o8HlHU7Cz3ISWhC3cxapm_IfuzB-YF4GpU0NsqPvynA1
                         referer: https://motor.compareunittest.com/
                         accept-encoding: gzip, deflate, br
                         accept-language: en-GB,en-US;q=0.9,en;q=0.8
                     --> parent_stream_id = 0
                     --> source_dependency = 129229 (HTTP_STREAM_JOB)
                     --> stream_id = 3
                     --> weight = 220
t=314535 [st=321]    HTTP2_SESSION_SEND_DATA
                     --> fin = true
                     --> size = 311
                     --> stream_id = 3
t=314535 [st=321]    HTTP2_SESSION_UPDATE_SEND_WINDOW
                     --> delta = -311
                     --> window_size = 1048265
t=314542 [st=328]    HTTP2_SESSION_RECV_RST_STREAM
                     --> error_code = "1 (PROTOCOL_ERROR)"
                     --> stream_id = 3
t=314653 [st=439]    HTTP2_SESSION_SEND_HEADERS
                     --> exclusive = true
                     --> fin = true
                     --> has_priority = true
                     --> :method: OPTIONS
                         :authority: autoservice.compareunittest.com
                         :scheme: https
                         :path: /api/mi/pagevisit
                         access-control-request-method: POST
                         origin: https://motor.compareunittest.com
                         user-agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36
                         access-control-request-headers: __requestverificationtoken,authorization,content-type,correlationid
                         accept: */*
                         accept-encoding: gzip, deflate, br
                         accept-language: en-GB,en-US;q=0.9,en;q=0.8
                     --> parent_stream_id = 0
                     --> source_dependency = 129239 (HTTP_STREAM_JOB)
                     --> stream_id = 5
                     --> weight = 220
t=314654 [st=440]    HTTP2_SESSION_RECV_WINDOW_UPDATE
                     --> delta = 311
                     --> stream_id = 0
t=314654 [st=440]    HTTP2_SESSION_UPDATE_SEND_WINDOW
                     --> delta = 311
                     --> window_size = 1048576
t=314913 [st=699]    HTTP2_SESSION_RECV_HEADERS
                     --> fin = false
                     --> :status: 200
                         allow: OPTIONS, TRACE, GET, HEAD, POST
                         server: Microsoft-IIS/10.0
                         public: OPTIONS, TRACE, GET, HEAD, POST
                         x-powered-by: ASP.NET
                         access-control-allow-origin: *
                         access-control-allow-headers: Origin, X-Requested-With, Content-Type, Accept, Authorization, Cache-Control, __RequestVerificationToken, CorrelationId
                         x-frame-options: SAMEORIGIN
                         date: Thu, 03 May 2018 14:48:25 GMT
                         content-length: 0
                     --> stream_id = 5
t=314914 [st=700]    HTTP2_SESSION_RECV_DATA
                     --> fin = true
                     --> size = 0
                     --> stream_id = 5
t=314925 [st=711]    HTTP2_SESSION_SEND_HEADERS
                     --> exclusive = true
                     --> fin = false
                     --> has_priority = true
                     --> :method: POST
                         :authority: autoservice.compareunittest.com
                         :scheme: https
                         :path: /api/mi/pagevisit
                         content-length: 364
                         correlationid: 72b3a477-1129-4ca4-a373-3bd6cdc2c5b0
                         origin: https://motor.compareunittest.com
                         authorization: 48iFi3wa47u4yT46TfwRj3dcC651N275Cn=
                         content-type: application/json;charset=UTF-8
                         accept: application/json, text/plain, */*
                         user-agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36
                         __requestverificationtoken: GmI53U-AOKgq8RZ92Qf59kazIktqpOEPVZ4LzF_uL562FYPOz2ylxk94VYG3dJwZm-ZwhrfMOYjvfPWovI37OJ4mI3yDG6Do2DaBGY0HkC41:kE5Uxfh3fNgktZIhW1XG84nflggp3EULxtJbu_NCHiBwPxrOMeOAxiI7CoBWMGH3o8HlHU7Cz3ISWhC3cxapm_IfuzB-YF4GpU0NsqPvynA1
                         referer: https://motor.compareunittest.com/
                         accept-encoding: gzip, deflate, br
                         accept-language: en-GB,en-US;q=0.9,en;q=0.8
                     --> parent_stream_id = 0
                     --> source_dependency = 129259 (HTTP_STREAM_JOB)
                     --> stream_id = 7
                     --> weight = 220
t=314925 [st=711]    HTTP2_SESSION_SEND_DATA
                     --> fin = true
                     --> size = 364
                     --> stream_id = 7
t=314925 [st=711]    HTTP2_SESSION_UPDATE_SEND_WINDOW
                     --> delta = -364
                     --> window_size = 1048212
t=314933 [st=719]    HTTP2_SESSION_RECV_RST_STREAM
                     --> error_code = "1 (PROTOCOL_ERROR)"
                     --> stream_id = 7
t=315213 [st=999]    HTTP2_SESSION_RECV_WINDOW_UPDATE
                     --> delta = 364
                     --> stream_id = 0
t=315213 [st=999]    HTTP2_SESSION_UPDATE_SEND_WINDOW
                     --> delta = 364
                     --> window_size = 1048576

I feel like there should be more information online on how to enable your apps to communicate using http2, but we arent finding anything.

Any help is appreciated!

Thanks

EDIT

I have also included the HTTP2 request we are making, saved from a HAR file in chrome:

"request": {
      "method": "OPTIONS",
      "url": "https://autoservice.compareunittest.com/api/mi/pagevisit",
      "httpVersion": "http/2.0",
      "headers": [
        {
          "name": ":path",
          "value": "/api/mi/pagevisit"
        },
        {
          "name": "access-control-request-method",
          "value": "POST"
        },
        {
          "name": "origin",
          "value": "https://motor.compareunittest.com"
        },
        {
          "name": "accept-encoding",
          "value": "gzip, deflate, br"
        },
        {
          "name": "accept-language",
          "value": "en-GB,en-US;q=0.9,en;q=0.8"
        },
        {
          "name": "user-agent",
          "value": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36"
        },
        {
          "name": "accept",
          "value": "*/*"
        },
        {
          "name": ":authority",
          "value": "autoservice.compareunittest.com"
        },
        {
          "name": ":scheme",
          "value": "https"
        },
        {
          "name": ":method",
          "value": "OPTIONS"
        },
        {
          "name": "access-control-request-headers",
          "value": "__requestverificationtoken,authorization,content-type,correlationid"
        }
      ],

And here is a response from the API when I switched back to HTTP1 and it responds correctly:

"response": {
      "status": 200,
      "statusText": "OK",
      "httpVersion": "HTTP/1.1",
      "headers": [
        {
          "name": "Date",
          "value": "Thu, 03 May 2018 16:33:19 GMT"
        },
        {
          "name": "Server",
          "value": "Microsoft-IIS/10.0"
        },
        {
          "name": "X-Frame-Options",
          "value": "SAMEORIGIN"
        },
        {
          "name": "X-Powered-By",
          "value": "ASP.NET"
        },
        {
          "name": "Allow",
          "value": "OPTIONS, TRACE, GET, HEAD, POST"
        },
        {
          "name": "Access-Control-Allow-Origin",
          "value": "*"
        },
        {
          "name": "Public",
          "value": "OPTIONS, TRACE, GET, HEAD, POST"
        },
        {
          "name": "Access-Control-Allow-Headers",
          "value": "Origin, X-Requested-With, Content-Type, Accept, Authorization, Cache-Control, __RequestVerificationToken, CorrelationId"
        },
        {
          "name": "Content-Length",
          "value": "0"
        }
      ],

Solution

  • So after trying all of the above, removing all lowercase strings from the header, removing the "__" from the request token, nothing was working. We were concatenating two tokens in the anti forgery request, and splitting them out on the API end. I noticed that the second static string had an "=" at the end of the string. We removed that from all apps, and it is now working with all HTTP1 and 2 requests!

    Thanks for the help! Check the characters in the headers is what I have learned from this.