I'm having a problem setting a content-type of application/json header on my post request.
saveUpdates(alltabs: AllTabs): Observable<Response> {
let api = this.host + this.routes.save;
let headers = new Headers();
headers.append('Content-Type', 'application/json');
return this._http.post(api, JSON.stringify(alltabs), { headers: headers })
.map((response: Response) => <Response>response.json())
.do(data => console.log("saveUpdates(): " + data))
.catch(this.handleError);
}
Request Headers:
OPTIONS /api/productsave HTTP/1.1
Host: wbtest:92
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Access-Control-Request-Method: POST
Origin: http://localhost:3000
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.84 Safari/537.36
Access-Control-Request-Headers: content-type
Accept: */*
Referer: http://localhost:3000/product/60000010080
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8
Response Headers:
HTTP/1.1 405 Method Not Allowed
Cache-Control: no-cache
Pragma: no-cache
Allow: POST
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/7.5
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Access-Control-Allow-Origin: *
Date: Tue, 14 Jun 2016 15:16:15 GMT
Content-Length: 76
As you can see, my request has two unexpected headers added "Access-Control-Request-Headers" and "Access-Control-Request-Method". This seems to suggest an issue with CORS (Cross-Origin Resource Sharing). However, the web.conf file on the API server has been working and the response headers states "Access-Control-Allow-Origin: *".
Any idea what could be wrong?
UPDATE:
The above code is correct - the problem is with the Sever code not being configured to handle preflight requests. In my case, the .NET Web API 2 application was not configured to allow CORS.
With CORS, you have two kinds of requests. As a matter of fact, the CORS specification distinguishes two distinct use cases:
Simple requests. This use case applies if we use HTTP GET, HEAD and POST methods. In the case of POST methods, only content types with the following values are supported: text/plain, application/x-www-form-urlencoded and multipart/form-data.
Preflighted requests. When the "simple requests" use case doesn't apply, a first request (with the HTTP OPTIONS method) is made to check what can be done in the context of cross-domain requests.
It seems that your server isn't configured to support preflighted request. The reason for the 405 status code (405 Method Not Allowed).
See this article for more details:
http://restlet.com/blog/2015/12/15/understanding-and-using-cors/
Related
Preflight response returns headers
server: uvicorn
access-control-allow-origin: *
access-control-allow-methods: DELETE, GET, HEAD, OPTIONS, PATCH, POST, PUT
access-control-max-age: 600
access-control-allow-headers: Accept, Accept-Language, Content-Language, Content-Type
content-length: 2
content-type: text/plain; charset=utf-8
for request with headers
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Access-Control-Request-Method: PATCH
Access-Control-Request-Headers: content-type
Referer: http://localhost:8080/
Origin: http://localhost:8080
Connection: keep-alive
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
But Firefox (102.0) rejects this with reason CORS Method Not Found.
POST and DELETE methods work fine, only PATCH is rejected. In Chrome, this request passes without problems.
In FastAPI, I have a middleware configured as following:
middleware=[Middleware(CORSMiddleware, allow_origins=["*"], allow_methods=["*"])],
Does anyone know what the problem may be? I also don't send any content/data in this PATCH request, I don't know if that's important.
I would like to make a file download resumable using byte-range requests.
The problem is that my existing download action is responding on a POST method and I would like to keep it that way.
But it seems from my early tests that Chrome turns interrupted POST requests for file downloads into GET requests when the user tries to resume and thus the resuming of the download fails.
Am I missing something?
Is this something related to the HTTP specs that only allow GET requests to be resumed?
Or is it simply a design flaw in Chrome (and maybe other browsers as well) that makes it forget the original HTTP method used?
UPDATE:
Here are the request/response data:
Initial POST request:
POST http://localhost:35547/Download?Guid=396b4697-e275-4396-818c-548bf8c0a281 HTTP/1.1
Host: localhost:35547
Connection: keep-alive
Content-Length: 0
Cache-Control: max-age=0
Origin: http://localhost:35547
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Referer: http://localhost:35547/File/396b4697-e275-4396-818c-548bf8c0a281
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.8
Cookie: __RequestVerificationToken=LuPgM05MHrsuyskgfhsrHVUs; ASP.NET_SessionId=gfiulghfuygisghkf; .ASPXAUTH=FGDJHGDHSDFB15AFDE6371CGJHDFGFBHD; fileDownload=true
Initial response (to the request above):
HTTP/1.1 200 OK
Cache-Control: private, s-maxage=0
Content-Type: application/zip
Server: Microsoft-IIS/7.5
X-AspNetMvc-Version: 5.2
Content-Disposition: attachment; filename="FILE-396b4697e2754396818c548bf8c0a281.zip"
X-AspNet-Version: 4.0.30319
Set-Cookie: fileDownload=true; path=/
X-Powered-By: ASP.NET
Date: Wed, 09 Nov 2016 11:13:50 GMT
Content-Length: 1885473
PK.......... ZIP file data .............................................
After the interruption, this is the request that the browser does on resume (notice the GET method used):
GET http://localhost:35547/Download?Guid=396b4697-e275-4396-818c-548bf8c0a281 HTTP/1.1
Host: localhost:35547
Connection: keep-alive
Referer: http://localhost:35547/File/396b4697-e275-4396-818c-548bf8c0a281
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36
Accept-Encoding: gzip, deflate, sdch, br
Accept-Language: en-US,en;q=0.8
Cookie: __RequestVerificationToken=.............
(Some data from security-related cookies have been shortened and altered)
Am I missing something ?
It depends, upon how have you analyzed the behavior of google chrome. Ideal way will be use any proxy or to use packet sniffer such as Wireshark to see what request method, is used by chrome in subsequent request.
Is this something related to the HTTP specs that only allow GET
requests to be resumed?
As of now, there's no mention in spec of HTTP protocol, that only GET requests can be resumed.
Or is it simply a design flaw in Chrome (and maybe other browsers as
well) that makes it forget the original HTTP method used?
Yes, It's the flaw of google chrome. Make sure that you check it on the latest version of Google chrome with all the update patches. Also check it on other browsers.
For more info about HTTP protocol, refer to https://www.ietf.org/rfc/rfc2616.txt.
Refer to following request, for serving partial response : https://en.wikipedia.org/wiki/Byte_serving
Edit
For more updated info regarding HTTP info, refer to :-
https://www.rfc-editor.org/rfc/rfc7230
I'm currently experiencing a problem where after clearing cache/cookies IE10 & IE11 will not set the cookie again. The requests and responses look almost identical but after clearing the cache the cookie is never passed up even though it appears to be set correctly.
Heres how my login method flows:
1. VerifyLogin() -> Fail: Go To Login page
-> Pass: Call rest of the AJAX Methods // Enter Login Credentials and submit
2. Authentication() -> Fail: Prompt the user
-> Pass: set forms auth cookie and navigate back to original page, where it will call VerifyLogin() again
This once Authentication() passes they should then slip through VerifyLogin() with no problem and continue using the product. All the calls will now have the forms authentication cookie passed up.
In the instance im seeing it fail, the Authentication() call passes and gets a 200 OK (and has a set-cookie response header) however, the VerifyLogin() then fails because it hasn't passed up the cookie.
I have had a real hard time reproducing this but so far the reproduction steps i have are as follows. This is starting with no instance of IE running. I'm not 100% sure this is the exact same issue my customers are experiencing however it seems to reveal the same problem they are seeing.
Start IE
Browse to the index page of the site and get bounced to the login (verify failed)
Login with credentials, Authentication() returns a 200 OK and has a set-cookie response header. It then navigates you and calls VerifyLogin() which passes. The cookie is sent up in the request and its all successful. Subsequent calls all work.
Clear my cache and cookies
Browse to the index page of the site and get bounced to the login (verify failed as it should)
Login with credentials, Authentication() returns a 200 OK and has a set-cookie response header. It then navigates you and calls VerifyLogin() at this point fails. The cookie isn't passed up in the request, even though it was previously set in the response of Authentication(). If i close and reopen IE it will work again.
So, its like the second time round the set-cookie response is just not setting the cookie.
Firstly, Heres the relevent sections of my web.config and how i set my forms cookie.
web.config:
<authentication mode="Forms">
<forms enableCrossAppRedirects="true" name="Gator.Express.Auth" timeout="2880" />
</authentication>
setAuthenticationCookie method:
public void SetAuthenticationCookie(string userName, CookieData cookieData)
{
//In order to pickup the settings from config, we create a default cookie and use its values to create a
//new one.
var cookie = FormsAuthentication.GetAuthCookie(userName, true);
var ticket = FormsAuthentication.Decrypt(cookie.Value);
if (ticket == null)
throw new Exception("Error setting authorisation cookie. Decryption of default cookie failed.");
var jsonToken = JsonConvert.SerializeObject(cookieData);
var newTicket = new FormsAuthenticationTicket(ticket.Version, ticket.Name, ticket.IssueDate, ticket.Expiration,
ticket.IsPersistent, jsonToken, ticket.CookiePath);
var encTicket = FormsAuthentication.Encrypt(newTicket);
cookie.Value = encTicket;
HttpContext.Current.Response.Cookies.Add(cookie);
}
Now below here are the requests and responses in order.
Working Authentication Request
POST http://localhost:55733/api/Authentication HTTP/1.1
Accept: application/json, text/javascript, */*; q=0.01
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: http://localhost:61496/Login.html
Accept-Language: en-GB
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko
Connection: Keep-Alive
Content-Length: 35
DNT: 1
Host: localhost:55733
Pragma: no-cache
Username=michaelGator&Password=XXXX
# Working Authentication Response
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
Set-Cookie: Gator.Express.Auth=01020FCCF4658183D208FE0F4CC8BA1385D208000C6D00690063006800610065006C004700610074006F00720000012F00FF; path=/; HttpOnly
Set-Cookie: Gator.Express.Auth=0102054E17668183D208FE05CEEABA1385D208010C6D00690063006800610065006C004700610074006F007200377B002200530073006F004100630063006F0075006E0074004900640022003A002200300030003000300030003000300030002D0030003000300030002D0030003000300030002D0030003000300030002D0030003000300030003000300030003000300030003000300022007D00012F00FF; expires=Sun, 05-Jul-2015 08:28:39 GMT; path=/; HttpOnly
X-SourceFiles: =?UTF-8?B?QzpcV29ya2luZ1xnYXRvci5nYXRvcndlYnNlcnZpY2VcU291cmNlXEdhdG9yV2ViU2VydmljZVxhcGlcQXV0aGVudGljYXRpb24=?=
Access-Control-Allow-Origin: http://localhost:61496
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization, token
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Credentials: true
Date: Fri, 03 Jul 2015 08:28:39 GMT
Content-Length: 14
"michaelGator"
# Working VerifyLogin Request
GET http://localhost:55733/api/VerifyLogin HTTP/1.1
Referer: http://localhost:61496/
Accept: */*
Accept-Language: en-GB
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko
Connection: Keep-Alive
DNT: 1
Host: localhost:55733
Cookie: Gator.Express.Auth=0102054E17668183D208FE05CEEABA1385D208010C6D00690063006800610065006C004700610074006F007200377B002200530073006F004100630063006F0075006E0074004900640022003A002200300030003000300030003000300030002D0030003000300030002D0030003000300030002D0030003000300030002D0030003000300030003000300030003000300030003000300022007D00012F00FF
# Working VerifyLogin response
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?QzpcV29ya2luZ1xnYXRvci5nYXRvcndlYnNlcnZpY2VcU291cmNlXEdhdG9yV2ViU2VydmljZVxhcGlcVmVyaWZ5TG9naW4=?=
Access-Control-Allow-Origin: http://localhost:61496
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization, token
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Credentials: true
Date: Fri, 03 Jul 2015 08:28:39 GMT
Content-Length: 0
Below here is the non-working set of requests and responses. Note that the Authentication method returns a 200 OK and a set-cookie command but in the next verify login call, the coookie is gone.
# Authentication Request - Returns as it should but part of the non-working set of requests
POST http://localhost:55733/api/Authentication HTTP/1.1
Accept: application/json, text/javascript, */*; q=0.01
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: http://localhost:61496/Login.html
Accept-Language: en-GB
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko
Connection: Keep-Alive
Content-Length: 35
DNT: 1
Host: localhost:55733
Pragma: no-cache
Username=michaelGator&Password=XXXX
# Authentication Response- Returns as it should but part of the non-working set of requests
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
Set-Cookie: Gator.Express.Auth=01022054EB9B8183D208FE20D4BEF01385D208000C6D00690063006800610065006C004700610074006F00720000012F00FF; path=/; HttpOnly
Set-Cookie: Gator.Express.Auth=01028447109C8183D208FE84C7E3F01385D208010C6D00690063006800610065006C004700610074006F007200377B002200530073006F004100630063006F0075006E0074004900640022003A002200300030003000300030003000300030002D0030003000300030002D0030003000300030002D0030003000300030002D0030003000300030003000300030003000300030003000300022007D00012F00FF; expires=Sun, 05-Jul-2015 08:30:10 GMT; path=/; HttpOnly
X-SourceFiles: =?UTF-8?B?QzpcV29ya2luZ1xnYXRvci5nYXRvcndlYnNlcnZpY2VcU291cmNlXEdhdG9yV2ViU2VydmljZVxhcGlcQXV0aGVudGljYXRpb24=?=
Access-Control-Allow-Origin: http://localhost:61496
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization, token
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Credentials: true
Date: Fri, 03 Jul 2015 08:30:10 GMT
Content-Length: 14
"michaelGator"
# Non-Working VerifyLogin Request - note, no cookie passes up
GET http://localhost:55733/api/VerifyLogin HTTP/1.1
Referer: http://localhost:61496/
Accept: */*
Accept-Language: en-GB
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko
Connection: Keep-Alive
DNT: 1
Host: localhost:55733
# Non-Working VerifyLogin response - Fails as no Forms Cookie was passed up
HTTP/1.1 401 Unauthorized
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?QzpcV29ya2luZ1xnYXRvci5nYXRvcndlYnNlcnZpY2VcU291cmNlXEdhdG9yV2ViU2VydmljZVxhcGlcVmVyaWZ5TG9naW4=?=
Access-Control-Allow-Origin: http://localhost:61496
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization, token
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Credentials: true
Date: Fri, 03 Jul 2015 08:30:10 GMT
Content-Length: 71
{"$id":"1","Message":"Authorization has been denied for this request."}
Any one have any ideas on this?
You seem to get getting two authentication cookies, which suggests that your implementation is clashing with something that ASP.Net is trying to automate for you.
There is a FormsAuthentication.SetAuthCookie that creates and sets the cookie, and I think this has already applied, so:
FormsAuthentication.SetAuthCookie gets the cookie (already set in the same response).
Your SetAuthenticationCookie fires.
This calls FormsAuthentication.GetAuthCookie and processes (embeds JSON serialised data into a new cookie) the original.
You call HttpContext.Current.Response.Cookies.Add to create a second cookie.
Both cookies are delivered in the header with the same name
You haven't cleared the original cookie, and .Net doesn't know how to process your processed cookie.
I think you have two options:
Split out your JSON data into a completely separate cookie with a different name.
Roll your own cookies from scratch and don't use any of .Net's FormsAuthentication methods.
I'd personally go with the former as the simplest and quickest to implement.
It might also be worth experimenting with cookie names - I'm not sure all browsers support periods in cookie names, but they are all case sensitive.
Finally something else worth checking - it's almost never worth setting a cookie's path in .Net, as IIS treats URL as case insensitive, but browsers all treat cookie names as case-sensitive.
Why is the response sending two SetCookie headers with the same cookie name? That seems… wrong and confusing.
Be careful not to give IE too much data in cookies. Your cookie values are pretty long! There is a cookie limit of ~4k. That’s total cookies for your domain. If it is longer than that, IE will not send it back.
HTH
During development of an IIS module for basic authentication, I stocked to a problem. The module is working fine when browsing the pages, but when calling web-services it seems that request does not reach the module and some in-the-middle module takes control of request.
using fiddler, I found out when Content-type in http request header is set to application/json that in the middle module/handler is triggered. so following request does not work:
when working fine, the server should ask client to send the user credentials by setting the WWW-Authenticate header in response
GET /WebServices/service.asmx/someMethod?param=test HTTP/1.1
Host: localhost
Connection: keep-alive
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.152 Safari/537.22
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Content-Type: application/json
asdfasdf
asdfasdfasdf
response: notice the jsonerror header in response
HTTP/1.1 401 Unauthorized
Content-Type: application/json; charset=utf-8
Server: Microsoft-IIS/7.5
jsonerror: true
X-Powered-By: ASP.NET
Date: Mon, 11 Mar 2013 23:49:02 GMT
Content-Length: 105
{"Message":"Authentication failed.","StackTrace":null,"ExceptionType":"System.In
validOperationException"}
where this one works fine: notice that there is no content-type
GET /WebServices/service.asmx/someMethod?param=test HTTP/1.1
Host: localhost
Connection: keep-alive
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.152 Safari/537.22
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
asdfasdf
asdfasdfasdf
and the correct response is: notice the WWW-Authenticate header in response
HTTP/1.1 401 Unauthorized
Location: http://localhost/WebServices/service.asmx/someMethod?param=test
Server: Microsoft-IIS/7.5
WWW-Authenticate: Basic
X-Powered-By: ASP.NET
Date: Mon, 11 Mar 2013 23:59:48 GMT
Content-Length: 0
Well, that in-the-middle module was ScriptModule where we had both 3.5 and 4.0 version being added in the config. inspecting them through dotpeek, I found that the script module checks request's content-type against being application/json and then tries to handle the request as a REST request or webservice call.
By removing them, nothing special happened. I assume that they are to be used when script manager or Microsoft Specific AJAX services are used. You can find more about it in
ASP.Net Ajax Programming Tricks
I've read all the caching documentation for HTTP, and this are the headers for my file:
Edit: I am now using amazon S3 to see if it helps and still the same problem! Here go the request and the response> What am I missing? Even thought the response asks for the browser to cache the file, it doesn't! I've checked the Google Chrome cache and the file is not there.
Request URL:https://s3-sa-east-1.amazonaws.com/combo-combat-release/WebPlayer.unity3d
Request Method:GET
Status Code:200 OK
**Request Headers**
GET /combo-combat-release/WebPlayer.unity3d HTTP/1.1
Host: s3-sa-east-1.amazonaws.com
Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.52 Safari/537.17
Accept: */*
Accept-Encoding: gzip,deflate,sdch
Accept-Language: es,en-US;q=0.8,en;q=0.6
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
**Response Headers**
HTTP/1.1 200 OK
x-amz-id-2: xu/RKgR4Xt6G3jQ1qkdO5rzd4TlngDYYERZ+bbGlalitJFMDjAgiLAoP4GXhmkeo
x-amz-request-id: 6A9389D16407D28D
Date: Wed, 16 Jan 2013 22:42:26 GMT
Cache-Control: max-age=2592000, public, must-revalidate
Last-Modified: Wed, 16 Jan 2013 22:29:55 GMT
ETag: "0f8d22257da9fcae61f21fd30b7a1fd4"
Accept-Ranges: bytes
Content-Type: application/octet-stream
Content-Length: 39222189
Server: AmazonS3
But the browser doesn't cache the file. Each time, the request is sent and all the data transferred from scratch (200 OK instead of 304). :(
File size is 37.4 MB
Any tip on what could be wrong?
Thanks,
Manuel
Try HTTP 1.1 instead of 1.0.
http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html states:
Note that HTTP/1.0 caches might not implement Cache-Control and
might only implement Pragma: no-cache