I am new to Flutter and I am trying to call my ASP.NET server web API.
From the logs on my server, everything goes fine but Android Studio throws an exception: "invalid header field name".
Here is the code in dart:
import 'package:http/http.dart' as http;
...
_getService() async {
String result;
try {
var url = 'http://192.168.1.14:34263/api/Mobile/test/1';
Future<http.Response> response = http.get( url );
result = response.toString();
} catch(exception){
result = exception.toString();
debugPrint(result);
}
...
}
Here is the response header (obtained via Chrome):
Access-Control-Allow-Headers:accept, authorization, Content-Type
Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, PATCH, DELETE
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: WWW-Authenticate
Cache-Control: no-cache
Content-Encoding: deflate
Content-Length:79
Content-Type: application/xml; charset=utf-8
Date: Thu, 08 Mar 2018 01:01:25 GMT
Expires:-1
Pragma:no-cache
Server:MyTestServer
X-Content-Type-Options:NOSNIFF
X-Permitted-Cross-Domain-Policies:master-only
X-SourceFiles:=?UTF-8?BDpcTXlJbmNyZWRpYmxlRHJlc3NpbmdcTXlJbmNyZWRpYmxlRHJlc3NpbmdcTXlJbmNyZWRpYmxlRHJlc3NpbmdcYXBpXE1vYmlsZVxjb3Vjb3VcMQ==?=
X-XSS-Protection:1;mode=block
Here is the answer which is returned:
<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">test</string>
Can anyone tell me what am I doing wrong?
Many thanks
Ok, I finally found out, by debugging the code.
In fact, my server added a series of field names in the response's header (via the Web.config) and the last character of one of these field names was a space.
As a result, the http_parser.dart threw an exception since spaces are no authorized characters in header field name.
Nothing was detected by Chrome (or any browser) nor by Postman.
I had similar problem and after some heavy debugging
I removed these headers from nginx:
#add_header X−Content−Type−Options nosniff;
#add_header X−Frame−Options SAMEORIGIN;
#add_header X−XSS−Protection 1;
and it works fine. So most likely it's backend - header related issue
Related
i have a implementation for oauth 2.0 in Java, i wanted to try out some things with the Shopware 6 API. I can get the access token without problems and, as far as i see, i'm doing everything right to request a ressource with this access_token. In the header for the GET Request i put the 'Authorization Bearer' + access_token header and also the "Content-Type", "application/json" header.
HttpGet get = new HttpGet(resourceURL);
get.addHeader("Content-Type", "application/json");
and later
if (isValid(accessToken)) {
// update the access token
// System.out.println("New access token: " + accessToken);
oauthDetails.setAccessToken(accessToken);
// remove the old auth header
get.removeHeaders(OAuthConstants.AUTHORIZATION);
// add the new auth header
get.addHeader(OAuthConstants.AUTHORIZATION,
getAuthorizationHeaderForAccessToken(oauthDetails.getAccessToken()));
get.releaseConnection();
response = client.execute(get);
code = response.getStatusLine().getStatusCode();
The Error Code i always get is 415.
This is the complete response:
HttpResponseProxy{HTTP/1.1 415 Unsupported Media Type [Date: Thu, 04 Jul 2019 08:45:38 GMT, Server: Apache/2.4.25 (Debian), Cache-Control: no-cache, private, Access-Control-Allow-Origin: *, Access-Control-Allow-Methods: GET,POST,PUT,PATCH,DELETE, Access-Control-Allow-Headers: Content-Type,Authorization,sw-context-token,sw-access-key,sw-language-id,sw-version-id, sw-version-id: , sw-language-id: , sw-context-token: , x-frame-options: deny, X-Debug-Token: c1766c, X-Debug-Token-Link: http://localhost:8000/_profiler/c1766c, X-Robots-Tag: noindex, Vary: Authorization, Keep-Alive: timeout=5, max=100, Connection: Keep-Alive, Transfer-Encoding: chunked, Content-Type: application/json] ResponseEntityProxy{[Content-Type: application/json,Chunked: true]}}
The endpoint im trying to get is the "http://localhost:8000/api/v1/category/" endpoint. If im doing this whole thing with Insomnia/Postman i get the expected category information.
Does anyone have any idea what could be wrong? What am i missing here?
Please add following header
'Accept': 'application/json'
As nuriselcuk pointed out in the comment, the missing thing was the Accept header.
I added
post.addHeader("Accept", "application/json");
and now its working fine.
I have a problem with Google HTTP Client Library for Java (1.22.0).
This is my code
String url = "http://gazetapraca.pl/ogl/2502758";
GenericUrl genericUrl = new GenericUrl(url);
ApacheHttpTransport apacheHttpTransport = new ApacheHttpTransport();
HttpRequest httpRequest = apacheHttpTransport.createRequestFactory().buildGetRequest(genericUrl);
httpRequest.setFollowRedirects(true);
HttpResponse httpResponse = httpRequest.execute();
and httpRequest.execute() throws
com.google.api.client.http.HttpResponseException: 301 Moved Permanently
Below is follow from Wireshark
GET /ogl/2502758 HTTP/1.1
Accept-Encoding: gzip
User-Agent: Google-HTTP-Java-Client/1.22.0 (gzip)
Host: gazetapraca.pl
Connection: Keep-Alive
HTTP/1.1 301 Moved Permanently
Date: Sat, 26 Nov 2016 22:15:52 GMT
Server: Apache
Location: /ogl/2502758/pakowacz+-+mile+widziane+panie
Content-Length: 0
Set-Cookie: JSESSIONID_JOBS=2f1TffY6JYcb6zvBSrQ72fds7rfdsSnHM3sefw6D31Lfr434bnkDmdLQJLvLFZ6zkYBF!-12116034235597; path=/; HttpOnly
Content-Language: pl
P3P: CP="NOI DSP COR NID PSAo OUR IND"
Vary: User-Agent
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
GET /ogl/2502758/pakowacz%20-%20mile%20widziane%20panie HTTP/1.1
Accept-Encoding: gzip
User-Agent: Google-HTTP-Java-Client/1.22.0 (gzip)
Host: gazetapraca.pl
Connection: Keep-Alive
Cookie: JSESSIONID_JOBS=2f1TffY6JYcb6zvBSrQ72fds7rfdsSnHM3sefw6D31Lfr434bnkDmdLQJLvLFZ6zkYBF!-12116034235597
HTTP/1.1 301 Moved Permanently
Date: Sat, 26 Nov 2016 22:15:52 GMT
Server: Apache
Location: /ogl/2502758/pakowacz+-+mile+widziane+panie
Content-Length: 0
Content-Language: pl
P3P: CP="NOI DSP COR NID PSAo OUR IND"
Vary: User-Agent
Keep-Alive: timeout=2, max=99
Connection: Keep-Alive
and repeat a few times.
Maybe the problem is with url, because location is /ogl/2502758/pakowacz+-+mile+widziane+panie and next request method get is /ogl/2502758/pakowacz%20-%20mile%20widziane%20panie.
In other software and library everything is working (google chrome browser, postman - addon to chrome, JSOUP - java library).
Does anyone have an idea how to solve the problem?
This is not your library's fault.
To understand why this problem is occurring, we must first understand the "error" message associated with your problem:
com.google.api.client.http.HttpResponseException: 301 Moved Permanently
So, what does this mean? Well, the last part of the error message, the description says "301 Moved Permanently". What that is referring to is an HTTP Status Code. An HTTP Status Code indicates what the outcome of a specific request is. In this case, the status code was 301, which according to RFC protocol means:
The requested resource has been assigned a new permanent URI and any future references to this resource SHOULD use one of the returned URIs.
So, this means that the URL that you are using is no longer valid, and that you have to use the new URL given to you by the Location response header. Now, it seems that the library that you're using is smart enough to detect this, and initializes a new request to the new URL. That's great and all, but your library that you are using, is incorrectly escaping the url provided by the Location header, and using that for the new request (turning /ogl/2502758/pakowacz+-+mile+widziane+panie into /ogl/2502758/pakowacz%20-%20mile%20widziane%20panie), and the server receiving this request recognizes that those to paths are not the same (even though they should be. So, the server sends another 301 response, telling the client (the library in this case) to use the un-escaped URL instead of the escaped one, even though they should be the same.
Now, why is your library doing this? It turns out that, according to RFC spec, the '+' character is reserved for URIs. That means that that character, along with other characters are only intended for use in URIs for their intended purpose. Therefore, it is not standard to include the '+' character in URIs, unless it is used for a very specific purpose, which it looks like is not the case.
So, this all means that you cannot blame the library for this error, you can only blame the people who developed this site.
The reason that this works in your browser and other places is because those clients do not seem to be escaping the requested URL for you before sending it to the server.
I'm following these steps to create a PUT request by using V4: http://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-header-based-auth.html
Just created a JSP for trying to upload a file to a S3 bucket. The issue is I always get a 403 - Forbidden. By looking at the response in detail, it says is a 'SignatureDoesNotMatch' error, the message is 'The request signature we calculated does not match the signature you provided. Check your key and signing method.'
The content is actually just the string 'File contents'. These are the headers sent:
PUT /test.txt HTTP/1.1
Accept: /
Host: my host.s3.amazonaws.com
Date: Thu, 22 Sep 2016 04:51:52 GMT
Authorization: AWS4-HMAC-SHA256 Credential=My access ID/20160922/us-east-1/s3/aws4_request,SignedHeaders=date;host;x-amz-content-sha256;x-amz-date;x-amz-storage-class,Signature=1bqb/RTdtsOP42zs7UR4d6Id6YlNgIbO86Q1m2RuGFs=
x-amz-date: 20160922T045152Z
x-amz-content-sha256: 69423BABE8E61AAB549F347BCC8B9D77B7DCACA198FB0597BDE0B5F97F968E38
x-amz-storage-class: REDUCED_REDUNDANCY
Content-Type: text/plain
Content-Length: 13
The significant parts of the response body are these:
<CanonicalRequest>PUT
/test.txt
content-length:13
content-type:text/plain
date:Thu, 22 Sep 2016 04:51:52 GMT
host:my host.s3.amazonaws.com
x-amz-content-sha256:69423BABE8E61AAB549F347BCC8B9D77B7DCACA198FB0597BDE0B5F97F968E38
x-amz-date:20160922T045152Z
x-amz-storage-class:REDUCED_REDUNDANCY
content-length;content-type;date;host;x-amz-content-sha256;x-amz-date;x-amz-storage-class
69423BABE8E61AAB549F347BCC8B9D77B7DCACA198FB0597BDE0B5F97F968E38</CanonicalRequest>
<StringToSign>AWS4-HMAC-SHA256
20160922T045152Z
20160922/us-east-1/s3/aws4_request
17957a94c148833cd2f1132a8a4ffcfe6d2c83a71501a063f7a2ff9e7acfa1aa</StringToSign>
<SignatureProvided>1bqb/RTdtsOP42zs7UR4d6Id6YlNgIbO86Q1m2RuGFs</SignatureProvided>
I'm pretty sure that CanonicalRequest and StringToSing are equal on the response I get and the request I'm creating, since we are logging all this info for debugging for now. Just by comparing, I can ensure the data is exactly the same except for the '=' character at the end of the signature:
Signature at Authorization Header:
1bqb/RTdtsOP42zs7UR4d6Id6YlNgIbO86Q1m2RuGFs=
SignatureProvided at response body:
1bqb/RTdtsOP42zs7UR4d6Id6YlNgIbO86Q1m2RuGFs
I just cannot figure out why I get this SignatureDoesNotMatch error, it seems to be everything Ok (except for this '=' character, I don't know why is not being included on the SignatureProvided at the response). I have attached the code I'm using to create the request.
Is there something I'm missing? Is the first time I try to integrate with AWS. I have already spent many days trying to get it to work, it's pretty annoying :(
Thanks in advance for your help!
EDIT: removing the last '=' character from the signature didn't worked, same result as above.
A quick google search told me that extra "=" is actually added by a padding factor and even quicker test case helped me in finding a way to encode without that padding.
#Test
public void testSign(){
byte[] b = Base64.getDecoder().decode("1bqb/RTdtsOP42zs7UR4d6Id6YlNgIbO86Q1m2RuGFs=");
System.out.println(Base64.getEncoder().withoutPadding().encodeToString(b));
}
Not suprisingly, If I remove withoutPadding(), I get = in the end, maybe you can use java.net.Base64 for encoding without padding.
I am using flash to upload a file to GCS.
I create a upload url using the following successUrl
"/cms/requestManager?ps={"1":{"action":"Upload Audio Recording","sendId":1,"data":{"fileName":"testQuestionAudioRecording","category":"testQuestionRecording"}},"jsInstanceID":"ahdzfmRldi1keW5hY3RpdmVzb2Z0d2FyZXITCxIKSlNJbnN0YW5jZRjKm-kBDKIBBmRzLmNtcw","userActive":true}"
When I send the file upload it comes back with a 404 error.
I check in the appengine instance logs for 404 errors and there are none.
The file I tried to upload does show up in the GCS bucket.
In the documentation for blobstoreService.createUploadUrl() it does not mention that query strings are not allowed. I would also expect that if there were something wrong with the successUrl that an IllegalArgumentException would be thrown.
If I go directly to the successUrl it will respond correctly with JSON data.
This is the link if you want to test
On my local test server it works fine. So I am seeing this issue only on production.
If I take out the query string, it will work. If I add a simpler query string like /cms/requestManager?blah=blah it will not work.
Does anyone have any ideas what is going on?
Is there a way to see what is happening on at /_ah/upload?
Could it be possible that it is 404ing on my end but not logging it? If so, what can I do find that out?
Here is the post and response headers and content.
Response Header:
HTTP/1.1 404 Not Found
Content-Length: 0
Date: Fri, 06 Mar 2015 00:25:25 GMT
Server: UploadServer ("Built on Feb 18 2015 18:10:26 (1424311826)")
Content-Type: text/html; charset=UTF-8
Alternate-Protocol: 80:quic,p=0.08
Request Headers:
POST /_ah/upload/AMmfu6a-yuYk7Gm1YMtqLt-GgyizWYLXRStoAZ49FCNNRHIVXMFrRh0Jo1aCSXf4c8uXrjJnCQwvSq7cFdVeI1v5J59jQeVfwvR6STMbs0hBw-GncTI1JHgE4NItQd2JQGgyHIqTasjR4lK_5g8-M0Nf1YdWr29by5Mskk07tpSLNUE0mEW2IOjlWP_Usa7ObJMFdElVqIsgd5a_Bq198AB9oprS6DMHkiYKsdJGCTmHe93w_PEoi-XiROlHSpEsi8TLwQUPPC86iqQsn6th4OGoRudOcdAVhFxCq1VJjXx2frv_Lm0khSxpmOU2nQu8gsbP-IaAgVWMe-0UUgsLYdODjqJhgkr-IB1h05F50pAXTgzImQHyv7ygvOhHO0zGUBAiH1a072LJa7EiN1TXcBYcDfbbMikR5lBdaqfqHccx23RZrDiyGfR3kwMiXmgqFy5BJY5Ht9ZoYlfST76laeM5v2PSheMqweHIZQATBZ0Zxojzv1mFr3ECasfwEY98ambjjrbgqysPwg56B-EYDCwUBAV5FvzY6hIGKnhjun9-rorrx0CuKww/ALBNUaYAAAAAVPj2QZXMlxhUs1-Au6wnswd3PTvLwL_G/ HTTP/1.1
Host: dev-dynactivesoftware.appspot.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:36.0) Gecko/20100101 Firefox/36.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.7,es;q=0.3
Accept-Encoding: gzip, deflate
Cookie: ahdzfmRldi1keW5hY3RpdmVzb2Z0d2FyZXITCxIKSlNJbnN0YW5jZRjKm-kBDKIBBmRzLmNtcw=1425601513386
Connection: keep-alive
appid = dev-dynactivesoftware
successUrl length = 256
Link to blobstoreService.createUploadUrl documentation
UPDATE:
I wrote some stuff into our system that allowed for data that was in the query string to be put into the url. So instead of
/requestManager?ps={} it would be
/requestManager/My Action/lsdkjfalsdkfjaldkfjaldkjf
It also 404d so I changed it to have no spaces in the url.
/requestManager/MyAction/lsdkjfalsdkfjaldkfjaldkjf
and it did not 404.
Could it be that the upload service is having problems using successUrls that have special characters in it, like spaces and ?.
The successUrl that you send into blobstoreService.createUploadUrl() needs to be url encoded first. So I modified the code that gets the uploadUrl to be the following:
String successUrl = URLEncoder.encode("/requestManager/My Action/askldjfkajsdflkasdkjh", "UTF8");
String uploadUrl = blobstoreService.createUploadUrl(successUrl);
I also had to decode the url later so that it was usable.
It seems to me that if the successUrl has characters that need to be encoded (because the service will return a 404 if it doesn't) then it should throw "java.lang.IllegalArgumentException - If successPath was not valid."
It would also be nice if the uploadServer would return something with the 404 message to indicate that successUrl 404d and this is the url we tried. At that point we would be able to see what is going on a lot faster.
I guess the even better fix would be to just put the code that the dev server runs on live because the dev environment worked perfect.
I'm writing an Android media player that uses Java's HTTPUrlConnection class to access URL's. I was recently sent a bug report related to the following URL:
"http://listen.theradio.cc"
This URL redirects to "http://listen.theradio.cc/theradiocc.pls" which returns a playlist in PLS format. The problem I'm facing is that my application usually determines what to do with a URL best on the content-type header field. The URL I posted above returns a content-type of "application/octet-stream", which can be anything. So instead of trying to parse the returned playlist my application tries to play the URL (which fails, obviously). Is there any other way to effectively determine what type of content a URL is returning in a situation like this? Should I attempt to obtain an InputStream and check the first few lines of returned content?
Anything can be application/octet-stream thus it is misleading as the server does not return the expected content type for play-list.
Its better to fix in the server side.
Additionally doing a HEAD request it should be possible to know the information for the URL.
Making a curl request to http://listen.theradio.cc/theradiocc.pls returns following.
curl -i http://listen.theradio.cc/theradiocc.pls
HTTP/1.1 200 OK
Server: nginx
Date: Thu, 26 Apr 2012 03:44:42 GMT
Content-Type: application/octet-stream
Content-Length: 111
Last-Modified: Tue, 15 Nov 2011 23:57:04 GMT
Connection: keep-alive
Accept-Ranges: bytes
[playlist]
NumberOfEntries=1
File1=http://theradio.cc:8000/trcc-stream
Title1=TheRadio.CC
Length1=-1
Version=2
So things needs to be fixed and properly fixed!