How to fix Bad Request when writing AppProperties for the file - c#

There is a problem writing AppProperties for the file using the Google drive api. The request is executed, then an error is returned 400.
Request is sent via dotnet api:
public Resource ResourcePatch(string FileID, IDictionary<string, string> properties)
{
GoogleAPI.File file = new GoogleAPI.File() { AppProperties = properties };
var updateRequest = _driveService.Files.Update(file, FileId);
updateRequest.Fields = "id, appProperties";
file = updateRequest.Execute();
...
This is what is sent and what I get.
Request:
PATCH https://www.googleapis.com/drive/v3/files/1DUpjXjNro6LreMgyVbYW7k05eBes0A3o?fields=id%2C%20appProperties HTTP/1.1
User-Agent: Sberdisk google-api-dotnet-client/1.38.0.0 (gzip)
Authorization: Bearer ...
Content-Type: application/json; charset=utf-8
Host: www.googleapis.com
Content-Length: 49
Accept-Encoding: gzip, deflate
{"appProperties":{"SHARED_PROPERTY_NAME":"true"}}
Response, sometimes:
HTTP/1.0 200 This buggy server did not return headers
<html><title>Error 400 (Bad Request)!!1</title></html>
Sometimes:
HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: Mon, 01 Jan 1990 00:00:00 GMT
Date: Thu, 07 Feb 2019 12:39:13 GMT
Vary: Origin
Vary: X-Origin
Content-Type: application/json; charset=UTF-8
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Server: GSE
Alt-Svc: quic=":443"; ma=2592000; v="44,43,39"
Content-Length: 183
{
"id": "1nWtqhBYKSl0YhtLMypEx5rmAuo43-3Ts",
"appProperties": {
"SHARED_PROPERTY_NAME": "true"
}
}
Sometimes the request is executed, sometimes an Bad Request. I do't see system logic in this. What can be the reason?

Related

(failed)net::ERR_HTTP2_PROTOCOL_ERROR for JWT

I'm using this code in my .NET API:
jwtOptions.Events = new JwtBearerEvents()
{
OnAuthenticationFailed = c =>
{
c.NoResult();
Logger.LogException(c.Exception);
c.Response.StatusCode = 401;
c.Response.ContentType = "text/plain";
if (ApiConfig.IsDeveloping)
{
return c.Response.WriteAsync(c.Exception.ToString());
}
return c.Response.WriteAsync("An error occured processing your authentication.");
},
OnTokenValidated = c =>
{
if (c.Principal.IsInRole("SuperAdmin"))
{
c.HttpContext.Items["IsSuperAdmin"] = true;
}
return Task.CompletedTask;
}
};
But this causes my React client to not get the errors if the authentication token is invalid.
When I look at the Chrome's Network tab, I see this error:
(failed)net::ERR_HTTP2_PROTOCOL_ERROR
What should I do? What have I done wrong in my .NET code?
Update I realized that it depends on the token that I send. If I send a totally invalid token like lkjsdlkjf then I get the 401 response. But if I use a valid JWT token from internet that is invalid for my current session, I get this error.
Update 2
This is the request/response I logged using Wireshark. Request/response seem to be fine. But Chrome or Postman cannot understand it correctly:
GET /locale/data HTTP/1.1
X-Forwarded-Host: api.admin.example.local
X-Forwarded-Proto: https
Connection: Upgrade
Host: api.admin.example.local
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
User-Agent: PostmanRuntime/7.29.2
Accept: */*
Postman-Token: 02c8e0f2-0afb-4112-8abf-c4815ea66176
Accept-Encoding: gzip, deflate, br
HTTP/1.1 401 Unauthorized
Content-Type: text/plain
Date: Mon, 09 Jan 2023 07:47:32 GMT
Server: Kestrel
Cache-Control: no-cache, no-store, must-revalidate
Content-Encoding: br
Expires: 0
Pragma: no-cache
Transfer-Encoding: chunked
Vary: Accept-Encoding
Milliseconds: 2238
33
...An error occured processing your authentication.

Managing returncode from Newtonsoft.Json when not authorized

We have using an implementation login on a JWT portal.
When I post a valid user/pass, we have a token ok. But whe I post a invalid user/pass, the response has this format:
{StatusCode: 401, ReasonPhrase: 'Unauthorized', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
Pragma: no-cache
Cache-Control: no-cache
Set-Cookie: dnn_IsMobile=False; path=/; HttpOnly
Set-Cookie: .ASPXANONYMOUS=YrYcKYrviiUjmN7dSAd2DYWBO5W_Nj2yS_79eZ473OtallQXmOoE_6u73yOGOgBn0im8tE_dcUrIR74EYy_l8HKId7AvyY2OszmP1JrCkR6dLslS0; expires=Fri, 18-Nov-2016 06:11:07 GMT; path=/; HttpOnly
Set-Cookie: dnn_IsMobile=False; path=/; HttpOnly
Set-Cookie: .ASPXANONYMOUS=YrYcKYrviiUjmN7dSAd2DYWBO5W_Nj2yS_79eZ473OtallQXmOoE_6u73yOGOgBn0im8tE_dcUrIR74EYy_l8HKId7AvyY2OszmP1JrCkR6dLslS0; expires=Fri, 18-Nov-2016 06:11:07 GMT; path=/; HttpOnly
Set-Cookie: language=es-CO; path=/; HttpOnly
Set-Cookie: ARRAffinity=03cc22ac05b5cc76e788b382c1c33cccde1e727973fdb84dce1c542f8f1d9b46;Path=/;Domain=plcolabv2-pre.azurewebsites.net
X-AspNet-Version: 4.0.30319
WWW-Authenticate: Bearer bad-credentials
Date: Fri, 09 Sep 2016 19:31:07 GMT
Content-Length: 0
Expires: -1
}}
Please, how can I get the results on first line, and store it on a variable? (StatusCode: 401, ReasonPhrase: 'Unauthorized'). When I post invalid user/pass, variable response have null value.
My code:
....
// Request body
byte[] byteData = Encoding.UTF8.GetBytes(jOneLogin);
using (var content = new ByteArrayContent(byteData))
{
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
response = await client.PostAsync(uri, content);
}
var results = JsonConvert.DeserializeObject<dynamic>(response.Content.ReadAsStringAsync().Result);
var crAccessToken = results.accessToken;
....
Maybe, is a simple question, answered in the past, but I can't find a specific post for that.
Thanks in advance.
As you are using HttpClient, you can just check HttpResponseMessage.IsSuccessStatusCode before calling JsonConvert.DeserializeObject(). See this answer for an example.

How to get the header values in a GET request?

System.Net.WebRequest req = System.Net.WebRequest.Create(URL);
req.Proxy = null;
System.Net.WebResponse resp = req.GetResponse();
System.IO.StreamReader sr = new System.IO.StreamReader(resp.GetResponseStream());
string result = sr.ReadToEnd().Trim();
I have this code which makes a GET request on my URL and returns the JSON data. However, I also need to get the header values from it.
Example output of the URL is the following:
Content-Type: application/json
Content-Language: en
Expires: Sat, 01 Jan 2000 00:00:00 GMT
Vary: Cookie, Accept-Language
Pragma: no-cache
Cache-Control: private, no-cache, no-store, must-revalidate
Set-Cookie: csrftoken=66161e4f97cbf771199ff78cfeea835e; expires=Sat, 20-Feb-2016 06:49:03 GMT; Max-Age=31449600; Path=/
Set-Cookie: mid=VOgqXwABAAHBumwiwEqLc2ScukeD; expires=Fri, 16-Feb-2035 06:49:03 GMT; Max-Age=630720000; Path=/
Connection: close
Content-Length: 108
{"status":"ok","shift":18,"header":"638wprvx7lg5Um0dZzBAKfjIkML12ChQ","edges":100,"iterations":10,"size":42}
Using my code, I can get the last JSON data returned, but I also need the headers. How can I do that? Thanks.
You can use Headers property of HttpRequest
Ref
resp.Headers
to get the headers for the response.
The HttpWebRequest has a built in property called Headers.
Please have a look at the MSDN page here:
https://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.headers(v=vs.110).aspx
At the bottom of the page you'll find a very simpe code example that should get you started!

Why is HttpClient so much faster with HTTPS over HTTP?

I was investigating a strange bug the other day in which normalizing a URL would cause a massive 300% slowdown in my application:
if (!TryNormalize(uri, out uri))
throw new ArgumentException("URL is not a valid YouTube URL!");
string pageSource;
using (var http = new HttpClient())
pageSource = await http.GetStringAsync(uri);
When TryNormalize was commented out, GetStringAsync would take about .5s to complete. Yet when it was uncommented, downloading the string would take up to 2s. Turns out that TryNormalize was prefixing all the URLs it processed with "http://", and adding an extra S solved the problem.
So with that said, why does this happen? To my understanding, HTTPS should be slower because the string has to be encrypted before transmission from the server, while HTTP doesn't offer such an option. And even if I'm no expert on HTTP, 300% seems like quite a dramatic slowdown. Am I missing something here?
Edit: Source code of TryNormalize:
public static bool TryNormalize(string videoUri, out string normalized)
{
normalized = null;
var builder = new StringBuilder(videoUri);
videoUri = builder.Replace("youtu.be/", "youtube.com/watch?v=")
.Replace("youtube.com/embed/", "youtube.com/watch?v=")
.Replace("/v/", "/watch?v=")
.Replace("/watch#", "/watch?")
.ToString();
string value;
if (!Query.TryGetParamValue("v", videoUri, out value))
return false;
normalized = "http://youtube.com/watch?v=" + value; // replacing with HTTPS here results in 1.5s speedup
return true;
}
This is because there are many redirections when you use the variantions of youtube url. For example navigating to http://youtu.be/O3UBOOZw-FE results in two redirections.(see the Location header)
1.
HTTP/1.1 302 Found
Date: Fri, 21 Aug 2015 16:52:40 GMT
Server: gwiseguy/2.0
Location: http://www.youtube.com/watch?v=O3UBOOZw-FE&feature=youtu.be
Content-Length: 0
Content-Type: text/html
X-XSS-Protection: 1; mode=block
X-Frame-Options: SAMEORIGIN
2.
HTTP/1.1 301 Moved Permanently
Date: Fri, 21 Aug 2015 16:52:40 GMT
Server: gwiseguy/2.0
Content-Type: text/html; charset=utf-8
X-Content-Type-Options: nosniff
Expires: Tue, 27 Apr 1971 19:44:06 EST
Content-Length: 0
Cache-Control: no-cache
X-XSS-Protection: 1; mode=block; report=https://www.google.com/appserve/security-bugs/log/youtube
Location: https://www.youtube.com/watch?v=O3UBOOZw-FE&feature=youtu.be
X-Frame-Options: SAMEORIGIN
until you finally get the url https://www.youtube.com/watch?v=O3UBOOZw-FE&feature=youtu.be
Since those redirections are handled automatically by HttpClient, you only see the final result of 3 requests.

Constructing multipart response

Given the reposne of multiple HTTP request, I have to build a multipart response out of them. The problem I am faing is how to set the response headers of individual response in the final multipart response. For. eg.
HttpClient client = new HttpClient();
HttpRequestMessage request1 = new HttpRequestMessage(HttpMethod.Get, "http://www.xyx/Service.svc/resource1");
HttpResponseMessage response1 = client.SendAsync(request).Result;
HttpRequestMessage request2 = new HttpRequestMessage(HttpMethod.Get, "http://www.xyx/Service.svc/resource2");
HttpResponseMessage response2 = client.SendAsync(request).Result;
MultipartContent content = new MultipartContent("mixed", "----Boundary");
content.Add(response1.Content);
content.Add(response2.Content);
The response I am getting from it is like:
------Boundary
Content-Length: 99427
Content-Type: application/json; charset=utf-8
Last-Modified: Mon, 20 Jan 2014 06:15:50 GMT
{"DebugInfo":null}
------Boundary
Content-Length: 99427
Content-Type: application/json; charset=utf-8
Last-Modified: Mon, 20 Jan 2014 06:15:50 GMT
{"DebugInfo":null}
------Boundary--
Now I want to include the reposne header of each request as part of individual response as well in the final response, and it should look like
HTTP/1.1 200 OK
Content-Type: multipart/mixed; boundary=batch_pK7JBAk73-E=_AA5eFwv4m2Q=
Date: Tue, 22 Jan 2013 18:56:00 GMT
Expires: Tue, 22 Jan 2013 18:56:00 GMT
Cache-Control: private, max-age=0
Content-Length: 1972
--batch_pK7JBAk73-E=_AA5eFwv4m2Q=
Content-Type: application/http
Content-ID: <response-8a09ca85-8d1d-4f45-9eb0-da8e8b07ec83+1>
HTTP/1.1 200 OK
ETag: "lGaP-E0memYDumK16YuUDM_6Gf0/V43j6azD55CPRGb9b6uytDYl61Y"
Content-Type: application/json; charset=UTF-8
Date: Tue, 22 Jan 2013 18:56:00 GMT
Expires: Tue, 22 Jan 2013 18:56:00 GMT
Cache-Control: private, max-age=0
Content-Length: 247
{
"kind": "storage#objectAccessControl",
"id": "example-bucket/obj1/allUsers",
"selfLink": "https://www.googleapis.com/storage/v1beta2/b/example-bucket/o/obj1/acl/allUsers",
"bucket": "example-bucket",
"object": "obj1",
"entity": "allUsers",
"role": "READER"
}
--batch_pK7JBAk73-E=_AA5eFwv4m2Q=
Content-Type: application/http
Content-ID:
HTTP/1.1 200 OK
ETag: "lGaP-E0memYDumK16YuUDM_6Gf0/91POdd-sxSAkJnS8Dm7wMxBSDKk"
Content-Type: application/json; charset=UTF-8
Date: Tue, 22 Jan 2013 18:56:00 GMT
Expires: Tue, 22 Jan 2013 18:56:00 GMT
Cache-Control: private, max-age=0
Content-Length: 247
{
"kind": "storage#objectAccessControl",
"id": "example-bucket/obj2/allUsers",
"selfLink": "https://www.googleapis.com/storage/v1beta2/b/example-bucket/o/obj2/acl/allUsers",
"bucket": "example-bucket",
"object": "obj2",
"entity": "allUsers",
"role": "READER"
}
--batch_pK7JBAk73-E=_AA5eFwv4m2Q=
Content-Type: application/http
Content-ID:
HTTP/1.1 200 OK
ETag: "lGaP-E0memYDumK16YuUDM_6Gf0/d2Z1F1_ZVbB1dC0YKM9rX5VAgIQ"
Content-Type: application/json; charset=UTF-8
Date: Tue, 22 Jan 2013 18:56:00 GMT
Expires: Tue, 22 Jan 2013 18:56:00 GMT
Cache-Control: private, max-age=0
Content-Length: 247
{
"kind": "storage#objectAccessControl",
"id": "example-bucket/obj3/allUsers",
"selfLink": "https://www.googleapis.com/storage/v1beta2/b/example-bucket/o/obj3/acl/allUsers",
"bucket": "example-bucket",
"object": "obj3",
"entity": "allUsers",
"role": "READER"
}
--batch_pK7JBAk73-E=_AA5eFwv4m2Q=--
Does anyone know how to add them in MultipartContent in C#?
Got it. You can also add complete response to a MultipartContent as well.
MultipartContent content = new MultipartContent("mixed", "----Boundary");
content.Add(new HttpMessageContext(response1));
content.Add(new HttpMessageContext(response2));

Categories

Resources