How to annotate errors using Swashbuckle Swagger - asp.net-web-api

I've used the Swashbuckle swagger Nuget package in a .net framework webapi.
I'm trying to annotate api responses. It's great for success responses, I just specify the type of my object model:
[SwaggerResponse((int)HttpStatusCode.OK, Type = typeof(WebAPI.Models.APIResponse), Description = "Successful operation.")]
If I return an error like this:
return this.Request.CreateErrorResponse(HttpStatusCode.NotFound, "Document not found.");
I get the following json / xml responses
{
"Message": "Document not found."
}
<Error>
<Message>Document not found.</Message>
</Error>
If there is an unhandled exception, I will get an http 500 with a json / xml response like this (Not, the exception details are only returned when executing the rest call from the local machine.:
{
"Message": "An error has occurred.",
"ExceptionMessage": "This is a test error",
"ExceptionType": "System.Exception",
"StackTrace": " at WebAPI.Controllers.MyController.Post(Guid id) in ..."
}
<Error>
<Message>An error has occurred.</Message>
<ExceptionMessage>This is a test error</ExceptionMessage
<ExceptionType>System.Exception</ExceptionType>
<StackTrace> at WebAPI.Controllers.MyController.Post(Guid id) in ...</StackTrace>
</Error>
For these responses, how do I annotate them with Swashbuckle?
I've tried:
[SwaggerResponse((int)HttpStatusCode.InternalServerError, Type = typeof(HttpResponseMessage), Description = "Error.")]
[SwaggerResponse((int)HttpStatusCode.InternalServerError, Type = typeof(HttpResponseException), Description = "Error.")]
[SwaggerResponse((int)HttpStatusCode.InternalServerError, Type = typeof(Exception), Description = "Error.")]
In the model example section I either get the message "Object is not a primitive" as in the case of Exception and HttpResponse, or the example does not reflect what the response would actually look like. For example HttpResponseException looks like this in the swagger ui:
{
"Response": {},
"Message": "string",
"Data": {},
"InnerException": {},
"StackTrace": "string",
"HelpLink": "string",
"Source": "string",
"HResult": 0
}
<?xml version="1.0"?>
<HttpResponseException>
<!-- invalid XML -->
<Message>string</Message>
<Data>
<!-- additional elements allowed -->
</Data>
<!-- invalid XML -->
<StackTrace>string</StackTrace>
<HelpLink>string</HelpLink>
<Source>string</Source>
<HResult>1</HResult>
</HttpResponseException>

Related

How to set message for error reponse status in Spring MVC?

I have a spring mvc handler like this:
#PostMapping("jwtToken")
fun jwtToken(#RequestBody body: JWTToken)
{
val token = body.token
if(token.isNullOrBlank())
throw ResponseStatusException(HttpStatus.UNAUTHORIZED, "Empty token")
}
If i send it an incorrect input, that triggers the exception, i get a reponse body like this:
{
"timestamp": "2020-10-30T03:41:20.305+00:00",
"status": 401,
"error": "Unauthorized",
"message": "",
"path": "/auth/jwtToken"
}
Why is the 'message' field empty in the response when i did assign a message to the exception? How do i set the message field
It might be related to the updated behaviour of the Spring Boot.
https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.3-Release-Notes#changes-to-the-default-error-pages-content
server.error.include-message=always
in .properties should do the trick but I prefer to use my own extended classes like this:
class CustomException(message: String): Exception(message) { ... }

Multipart file (not given condition).Error-400(bad request)

My rest api is.
#PutMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUEpath="/{referenceNumber}")
public void updateCard(#RequestHeader(value = tenantId) String theTenantId,
#PathVariable String referenceNumber,#RequestParam(value = "card")MultipartFile multipartFile,HttpServletRequest request)
I need to check the condition like without browsing the file.
my input format is
Headers :
tenantId : ***
Body : selecting "formdata" (Postman), "multipart-formdata" (AdvancedRestClient)
card : without browsing file
Then i am getting the following error in Postman.
{
"timestamp": 1549351840816,
"status": 400,
"error": "Bad Request",
"exception": "org.springframework.web.multipart.support.MissingServletRequestPartException",
"message": "Required request part 'card' is not present",
"path": "/app-1.5.0/1.5/references/34a236d7-9305-402f-959d-8c83d5ededbb"
}
If i try in the AdvancedRest client with same input
I am getting the different error.
{
"timestamp": 1549352119229,
"status": 415,
"error": "Unsupported Media Type",
"exception": "org.springframework.web.HttpMediaTypeNotSupportedException",
"message": "Content type 'null' not supported",
"path": "/app-1.5.0/1.5/references/34a236d7-9305-402f-959d-8c83d5ededbb"
}
Is there any reason for different outputs and can i check the api without
browsing file.
#PutMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUEpath="/{referenceNumber}")
public void updateCard(#RequestHeader(value = tenantId) String theTenantId,
#PathVariable String referenceNumber,#RequestPart(required = false,value = "card")MultipartFile multipartFile,HttpServletRequest request){
}
User #RequestPart instead of #RequestParam

How to handle Exception and return proper HTTP code in Spring webflux?

I have a method which gives response using Mono.fromfuture(result) and which throws CustomException with 400 as status.
Now in my service class, when I call that method, the error and code I am throwing there is not getting propagated to my client(postman). Only the message is what I am seeing.
I am getting this below format: -
{
"timestamp": "2019-02-01T11:13:32.748+0000",
"path": "/some_url",
"status": 500,
"error": "Internal Server Error",
"message": "Unable to fetch Response"
}
Expectation (what I want to achieve) : -
{
"timestamp": "2019-02-01T11:13:32.748+0000",
"path": "/some_url",
"status": 400, // (my own status)
"error": "INVALID_ARGUMENT", // (my own error)
"message": "Unable to fetch Response"
}
My Code:-
public Mono<ResponseObject> fetchResponse(arg) {
return Mono.just(somedata which will give exception)
.flatMap(k -> callExternalService(k))
.onErrorMap(e -> Mono.error(
new BusinessException("Unable to fetch Response", e))
*/* e here is giving :-
"code" : 400,
"message" : "Request contains an invalid argument.",
"status" : "INVALID_ARGUMENT" */*
}
Have you looked at the documentation of the Response class?
You can create a Response of your own, using the static methods in the doc, and send it, instead of Mono.error, in the onErrorMap.
You have to return something like below:
ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).body(klass, Klass.class);
ServerResponse.status(status).build();//read doc and set for yourself
You can also check this link.

Google APi Bad Request

i try to implement Passes service of Google Api in our website but we always have error 400 problem
we follow this documentation
Giftcardclass: insert
i use postman for test
POST https://www.googleapis.com/walletobjects/v1/giftCardClass
Request body
{
"kind":"walletobjects#loyaltyObject",
"id":"test2.test",
"classId":"test.test",
"version":12,
"state":"active",
"issuername":"dsadasdasdas",
"barcode":{
"kind":"walletobjects#barcode",
"type":"ean13",
"value":"aaaa",
"alternateText":"aaaa"
}
}
jSon response
{ "error": {
"errors": [
{
"domain": "global",
"reason": "invalidArgument",
"message": "Bad Request"
}
],
"code": 400,
"message": "Bad Request" }
}
from the documentation seems that only id,issuerstate and reviewStatus are required.
Looks like your ids are formatted wrongly, it should be issuer_id.unique_id. See https://developers.google.com/pay/passes/rest/v1/giftcardclass#GiftCardClass.FIELDS.id for reference.

Multiple Precondition failed annotation using swashbuckle

I'm using swashbuckle to document my web api project and I cannot add multiple responses for precondition failed cases, swagger only shows the last one.
/// <response code="200">OK</response>
/// <response code="401">Unauthorized</response>
/// <response code="400">BadRequest</response>
/// <response code="412">ErrorCode = 1... </response>
/// <response code="412">ErrorCode = 2... </response>
/// <response code="412">ErrorCode = 3... </response>
Swashbuckle generates something like:
{
...
"responses": {
"200": {
"description": "OK"
},
"400": {
"description": "BadRequest"
},
"401": {
"description": "Unauthorized"
},
"412": {
"description": "ErrorCode = 3..."
}
}
...
}
Where I would like to see:
{
...
"412": {
"description": "ErrorCode = 1..."
},
"412": {
"description": "ErrorCode = 2..."
},
"412": {
"description": "ErrorCode = 3..."
}
}
Any thoughts about it?
Thanks in advance
What you are trying to achieve is not possible with Swashbuckle because it is not compliant with the Open API specification (aka Swagger). The responses object contains a list of possible responses. Each response has a name and a response object. The name can be default or a HTTP status code. According to the spec of a responses object there can be only one response object per status code:
Any HTTP status code can be used as the property name (one property per HTTP status code). Describes the expected response for that HTTP status code.
That being said, I doubt whether it is correct to add additional error codes to a 412 response. A conditional request might not reach your server in case a proxy server already knows the conditions won't be matched.

Resources