Home > Blockchain >  415 Content type not support when making GET request to Web API
415 Content type not support when making GET request to Web API

Time:04-23

I am getting a weird issue, where one of my API endpoints is failing with 415 Content type not supported when making an GET request, which I am beating my head off the wall trying to figure out why.

The weirder thing is that it works completely fine in Postman.

It has something to do with a URL rewrite I need to do, so I can route the request to the appropriate server. If I do not do the rewrite, it works as well.

The redirect code is very basic, it just gets the identity for the request and gets the server's address. For context, I need to route to different servers based on the requests settings for GDPR compliance. If someone has a better method for doing this, I am all ears.

public class ProxyHandler : DelegatingHandler
    {
        private async Task<HttpResponseMessage> RedirectRequestAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            var identity = await GetIdentityAsync(request) as ParsedIdentity;

            using (var client = new HttpClient())
            {
                var clonedRequest = await request.CloneAsync();

                clonedRequest.RequestUri = new Uri(identity.Server.ApiUri   request.RequestUri.PathAndQuery);

                return await client.SendAsync(clonedRequest, HttpCompletionOption.ResponseHeadersRead, cancellationToken);
            }
        }

///Clone Async Extension
public static async Task<HttpRequestMessage> CloneAsync(this HttpRequestMessage req)
        {
            HttpRequestMessage clone = new HttpRequestMessage(req.Method, req.RequestUri);

            if (req.Content.Headers.ContentLength != null && req.Content.Headers.ContentLength > 0)
            {
                var contentStream = new StreamReader(await req.Content.ReadAsStreamAsync().ConfigureAwait(false));

                contentStream.BaseStream.Seek(0, SeekOrigin.Begin);

                clone.Content = new StreamContent(contentStream.BaseStream);

                // Copy the content headers
                if (req.Content.Headers != null)
                    foreach (var h in req.Content.Headers)
                        clone.Content.Headers.Add(h.Key, h.Value);
            }


            clone.Version = req.Version;

            foreach (KeyValuePair<string, object> prop in req.Properties)
                clone.Properties.Add(prop);

            foreach (KeyValuePair<string, IEnumerable<string>> header in req.Headers)
                clone.Headers.TryAddWithoutValidation(header.Key, header.Value);

            return clone;
        }

I have stepped through the code and observed it reaching the expected server, authenticating, and checked the RouteData to make sure it is the correct controller and method. I have checked to make sure the method is a GET and that there is no body of the request. It is all correct. However, as soon as it hands off the request to the controller, it doesn't reach it and returns 415 Content type not supported

I have even gone so far as to completely recreate a new request, rather than clone it (for this specific request) and it still does it.

More bizarrely, is that so far, I have only identified ONE request that does this. Every other GET,POST,PUT,PATCH,DELETE works. It is just this one request that fails. It is driving me nuts. Especially that it works in Postman.

Any help is appreciated, I have spent way too much time trying to figure this out.

Request
{
    "Method": "GET",
    "Url": "http://localhost:4201/site/en-us/menus/7aa17e5d-d500-4ee7-889e-66cad2f3057e?menuTypes=all,main-nav",
    "ServerVariables": "HTTP/1.1",
    "RequestGuid": "bc5a4bfb-09f4-4e7d-bee1-19774d6aae6d",
    "header_Connection": "Close",
    "header_Accept": "application/json",
    "header_Accept-Encoding": "gzip, deflate, br",
    "header_Accept-Language": "en-US, en; q=0.9",
    "header_Authorization": "my-token",
    "header_Host": "localhost:44358",
    "header_Referer": "http://localhost:4200/",
    "header_User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36 Edg/100.0.1185.44",
    "header_sec-ch-ua": "\" Not A;Brand\";v=\"99\", \"Chromium\";v=\"100\", \"Microsoft Edge\";v=\"100\"",
    "header_sec-ch-ua-mobile": "?0",
    "header_sec-ch-ua-platform": "\"Windows\"",
    "header_origin": "http://localhost:4200",
    "header_sec-fetch-site": "cross-site",
    "header_sec-fetch-mode": "cors",
    "header_sec-fetch-dest": "empty",
    "_env": "local"
}```

CodePudding user response:

I was able to fix this issue, however I am still not sure what the problem actually was, so if anyone can answer, it would be greatly appreciated.

I want to point out that this API has been used in a production system without the URL rewrite for around 3 years now and works fine from a browser or Postman. This issue only appears when coming from a browser through the proxy.

To fix it, I changed:

public async Task<HttpResponseMessage> GetMenus(Guid siteFirmUuid, string[] menuTypes, string locale = "en-us")

To:

public async Task<HttpResponseMessage> GetMenus(Guid siteFirmUuid, [FromUri]string[] menuTypes, string locale = "en-us")

I am aware of how parameter binding works, but I just do not understand why it works from Postman, works when called from the site directly, yet fails from the site going through the proxy when the FromUri attribute is missing.

At this point, I am glad it is fixed, but I am extremely interested in if anyone can help me figure out why this only failed in the specific instance I described above.

  • Related