What's the correct HttpStatusCode to return for a required parameter that's missing? [duplicate] - http-status-codes

This question already has answers here:
What HTTP status response code should I use if the request is missing a required parameter?
(10 answers)
Closed 9 years ago.
I'm building a Web API method to check if a name is unique of that type and need to make sure the name parameter is given. What's the correct status code to return?
public HttpResponseMessage GetIsNameUnique(string name)
{
if (string.IsNullOrWhiteSpace(layoutName))
{
throw new HttpResponseException(new HttpResponseMessage {
StatusCode = HttpStatusCode.{What Goes Here?},
Content = new StringContent("The name is required.")
});
}
// more code here to check....
}

400, or if the name parameter is part of the URI then you could return 404.

EDIT: 400 seems to be the best answer, rather than the 412, I mentioned below.
After looking at the link provided by codebox in the comment of this question, I'm going to go with 412, PreconditionFailed. From the System.Net.HttpStatusCode file
// Summary:
// Equivalent to HTTP status 412. System.Net.HttpStatusCode.PreconditionFailed
// indicates that a condition set for this request failed, and the request cannot
// be carried out. Conditions are set with conditional request headers like
// If-Match, If-None-Match, or If-Unmodified-Since.

Related

SpringBoot WebClient - exchangeToMono

I need to make a external API call from my Spring service. I am planning to return a Response object,
containing status code, actual json response. So that, the caller can decide how to decode the json based on the status code. Example - If status is 2xx - save the response, 4xx - log it in some error table etc.
I have done something like this. But, I am not sure whether the approach is correct or not.
Basically, I need to return the json and the status code for all status codes.
Wondering, how to achieve this with exchangeToMono.
The below code snippet works fine but I am not sure it's correct or not.
Appreciate any help or suggestions...
ResponseObj has two properties - statusCode and json.
public ResponseObj getExternalData() {
ResponseObj obj = new ResponseObj();
Mono<String> result = webclient.get().
.uri("/some/external/api")
.headers( //headers)
.exchangeToMono( response -> {
obj.setStatusCode(response.rawStatusCode());
return response.bodyToMono(String.class);
});
obj.setJson(result.block));
return obj;
}

webRequest API redirect uses http method of parent request

I'm using the webRequest-API in a WebExtension to monitor requests made by the client. This works quite well, however the API doesn't behave as expected in case of a redirect:
In this case a POST is issued which is answered with a 302 FOUND and a new location. My browser (Firefox 57, other versions and other browsers - e.g. Chrome - act the same way) follows this redirect and now issues a GET to the new location.
Unfortunately the webRequest-API behaves differently: It traces the first POST (which is correct) but than handles the second request as a POST, too, whereas it should be a GET. This is a severe problem since the API traces something my browser supposedly did, which it actually did in another way...
This scenario (the browser-part) can be reproduced by following this link to surfnet.nl and choosing an IDP form the list (e.g. Academisch Medisch Centrum).
So, long story short: Why does the webRequest-API behave different form the way browsers behave? And is there a way to let it exactly trace the browser's actions?
Interestingly the webRequest-API might do it correctly, regarding the documentation:
Even if the specification requires the method, and the body, not to be altered when the redirection is performed, not all user-agents conform here [browsers obviously change the method!], and you can still find buggy software out there. It is therefore recommended to set the 302 code only as a response for GET or HEAD methods and to use 307 Temporary Redirect instead, as the method change is explicitly prohibited in that case.
In the cases where you want the method used to be changed to GET, use 303 See Other instead.
EDIT:
It seems as if browser change the method on a 302 due to historical reasons, even tho it contradicts RFC 2616...
https://stackoverflow.com/a/8139246/594832
https://trac.ietf.org/trac/httpbis/ticket/160
https://stackoverflow.com/a/8138447/594832
Anyways... the question remains: how can I induce the webRequest-API to act the same way?
For anyone interested, I ended up with the following:
The docs let me to this (redirectUrl):
[...] Redirects initiated by a redirect action use the original request method for the redirect, with one exception: If the redirect is initiated at the onHeadersReceived stage, then the redirect will be issued using the GET method. [...]
Although the statement above gave me some hope, the method of that redirected request was still labeled as a POST...
So I updated the code to something roughly like this:
// Keep track of all requests issued so far and their responses
var httpRequests = [];
// Redirected requests come in with their originating parents' ID
browser.webRequest.onBeforeRequest.addListener(request => {
// Check if the request is a redirect
var isRedirected = function(requestId) {
var parentRequest = httpRequests.find(r => r.req.requestId === requestId);
if (parentRequest != null && parentRequest.res != null && parentRequest.res.statusCode === 302) {
return true;
}
return false;
};
// The webRequest-API seems to keep the HTTP verbs which is correct in resepct to RFC 2616 but
// differs from a typical browser behaviour which will usually change the POST to a GET. So do we here...
if (request.method === 'POST' && isRedirected(request.requestId)) {
console.log(`Redirected 302-request '${request.requestId}' is a POST but is here changed to a GET to conform to browser behaviour...`);
request.method = 'GET';
}
// Store the request
var entry = {
id: id,
req: request
};
httpRequests.push(entry);
});
browser.webRequest.onHeadersReceived.addListener(response => {
// Store the response alongside the request
var entry = httpRequests.find(req => req.id === response.requestId);
entry.res = response;
// If it turns out that a request should be redirected...
if (response.statusCode === 302) {
var location = response.responseHeaders.find(header => header.name.toLowerCase() === "location");
console.log(`Redirecting request '${id}' to new location '${location.value}'...`);
// The new location is set as redirectUrl, which results in a new invocation of onBeforeRequest with
// the current requestId
return {
redirectUrl: location.value
};
}
});
What happens?
Say onBeforeRequest receives a new request 2640 which is a POST.
onHeadersReceived gets the response which says that this request should be redirected to a new location (302).
The code above does so by setting the redirectUrl to that new location.
Then onBeforeRequest is triggered again. The webRequest-API passes the same requestId to it (2640).
The code checks if there's a parent for this request, and in this case it's true.
The method (which is still POST) is then modified to GET.
For the request lifecycle have a look at the illustration in the docs.

How to change Web Api Core unauthorized behavior

The default ASP.NET Web Api Core behaviour for unauthorized request is to send 401/403 error with empty content. I'd like to change it by specifying some kind of Json response specifying the error.
But I struggle to find a right place where I can introduce these changes. Official documentation is of no help (read it all). I had a guess that may be I could catch UnathorizedException in my exception filter / middleware but it didn't work out (I guess it gets handled at authorization level or even not thrown at all).
So my question is how can I customize response behavior in case of unauthorized request.
With .Net Core 3 (or may be earlier as well) you can write a middleware to check if the context.Response has a status of 40x and then return a custom object. Below is roughly how I did it:
if (context.Response.StatusCode == (int)HttpStatusCode.Unauthorized)
{
var result = new MyStandardApiResponseDto
{
Error = new MyErrorDto
{
Title = "Unauthorized",
Messages = new List<string> { "You are not authorized to access the resource. Please login again." },
},
Result = null
};
await context.Response.WriteAsync(JsonConvert.SerializeObject(result));
}

HTTP 400 bad request when using POST

I am getting HTTP 400 when I POST some JSON using RestSharp PCL.
When I send a string, it seems that the \" is included. Which it should not. This might be the reason why the POST does not work.
I am probably missing something that I need to fill in but please do help me to understand what I am missing.
Here is the code I am using
public async Task<bool> DoPost<T>(string endPoint, T content) where T : class
{
var body = JsonConvert.SerializeObject(content);
var request = new RestRequest(endPoint, Method.POST);
request.AddParameter("application/json", body, ParameterType.RequestBody);
try
{
var response = await _client.Execute(request, _cancellationToken.Token);
if (response.IsSuccess)
{
return true;
}
}
catch (Exception e)
{
throw new GTSWebServiceException(e.Message, e);
}
return false;
}
Have you checked this: How to POST request using RestSharp I know you are including the content type in the first argument but maybe you can play with RequestFormat? I doubt that's needed though. Also, have you checked whether your string does actually contain an escaped character like a double quote on it? If you are also seeing that slash on strings could it also be because you are debugging it? What do you receive in the payload coming through in the server that returns you the bad request?

Return a list of error messages with 400 Bad Request response in Web API 2

How can I return a list of error messages from Web Api 2 with 400 Bad Request status code? See the example below. Usually I use BadRequest method to return the 400 status code but it doesn't have any overload where it accepts a collection of string. It has an overload where it accepts ModelStateDisctionary. Does it mean I will have to create ModelStateDictionary from a list of error messages?
[Route("")]
[HttpPost]
public IHttpActionResult Add(Object data)
{
var valid = _serviceLayer.Validate(data);
if(!valid)
{
var errors = valid.Errors;
// errors is an array of string
// How do I return errors with Bad Request status code here?
}
var updatedObject = _serviceLayer.Save(data);
return Ok(updatedObject);
}
As per Mike's comment, I am going to add a new class implementing IHttpActionResult to return a list of error messages with 400 Bad Request. Thanks Mark

Resources