I have a REST endpoint that is used to POST data. So far, I've documented in using swagger as below.
#POST
#OPTIONS
#Path("{serviceVersion}/{dataType}")
#Produces({MediaType.TEXT_PLAIN})
#Consumes({MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN})
#ApiOperation(value = "Post to Application",
notes = "End Point to post Data")
#ApiResponses(value = { #ApiResponse(code = 200, message = "Success"),
#ApiResponse(code = 400, message = "Bad Request"),
#ApiResponse(code = 500, message = "Internal server error (NON-retryable)") })
public String postData(#Context HttpServletRequest req,
#Context HttpServletResponse resp,
#ApiParam(value = "Service Version. Ex: v1", required = true, defaultValue="v1") #PathParam("serviceVersion")String serviceVersion,
#ApiParam(value = "Topic Name", required = true, defaultValue="topic") #PathParam("dataType")String dataType,
#ApiParam(value = "Delivery Mode", required = false) #QueryParam("deliveryMode")#DefaultValue("persistent") String deliveryMode,
#Context UriInfo uriInfo);
How can I document #Context HttpServletRequest req? I need this because I want to let user's submit data from swagger-UI.
PS: The way data is actually read from the request is request.getReader(); or request.getInputStream();
Related
I have a microservice that need to consume from another microservice. The thing is that the controller has an authentication header. So how can I get that token from it to make a call from this new rest client?
I have used swagger codegen to get the different endpoints that I need to check.
The interface is as follows:
#javax.annotation.Generated(value = "io.swagger.codegen.v3.generators.java.SpringCodegen", date = "2022-06-20T09:40:39.340424400+02:00[Europe/Berlin]")
#Api(value = "getRelationByCucoId", description = "the getRelationByCucoId API")
public interface GetRelationByCucoIdApi {
#ApiOperation(value = "Retrieve a list of CustomerIDs for a certain CucoId", nickname = "getRelationByCucoIdUsingGET", notes = "This is a description", response = CucoPerson.class, responseContainer = "List", tags={ "Customers", })
#ApiResponses(value = {
#ApiResponse(code = 200, message = "Successfully retrieved list", response = CucoPerson.class, responseContainer = "List"),
#ApiResponse(code = 400, message = "The provided CucoID format or length is incorrect (Integer up to 10 digit)"),
#ApiResponse(code = 401, message = "You are not authorized to view the resource, check if the JWT was provided in the header"),
#ApiResponse(code = 403, message = "Accessing the resource you were trying to reach is forbidden"),
#ApiResponse(code = 404, message = "The resource you were trying to reach is not found") })
#RequestMapping(value = "/getRelationByCucoId/{cucoId}",
produces = { "application/json" },
method = RequestMethod.GET)
ResponseEntity<List<CucoPerson>> getRelationByCucoIdUsingGET(#ApiParam(value = "cucoId",required=true) #PathVariable("cucoId") Integer cucoId
,#ApiParam(value = "Authentication Header" ) #RequestHeader(value="GS-AUTH-TOKEN", required=false) String GS_AUTH_TOKEN, #AuthenticationPrincipal Principal principal
);
}
And the implementation:
#Override
public ResponseEntity<List<CucoPerson>> getRelationByCucoIdUsingGET(Integer cucoId, String GS_AUTH_TOKEN, Principal principal) {
return new ResponseEntity<>(new ArrayList<>(), HttpStatus.OK);
}
So how can I get it authenticated?
Thanks!
I want to upload the file with spring boot and vue.
But, I have an error '415 : Unsupported MediaType'.
This is my spring boot controller.
#PostMapping(consumes = {MediaType.MULTIPART_FORM_DATA_VALUE}, produces = {MediaType.APPLICATION_JSON_VALUE})
#ResponseBody
#ApiOperation(value = "회원 가입", notes = "<strong>아이디와 패스워드</strong>를 통해 회원가입 한다.")
#ApiResponses({
#ApiResponse(code = 200, message = "성공"),
#ApiResponse(code = 401, message = "인증 실패"),
#ApiResponse(code = 404, message = "사용자 없음"),
#ApiResponse(code = 500, message = "서버 오류")
})
public ResponseEntity<User> register(
#RequestParam("file") MultipartFile file,) throws IllegalStateException, IOException, URISyntaxException {
...
}
And, this is my vue code.
<el-form-item prop="profileImg" label="프로필 사진" :label-width="state.formLabelWidth" >
<input #change="fileSelect()" id="profileimg" type="file" accept="image/*">
</el-form-item>
const formData = new FormData()
formData.append('userId', state.form.userId)
formData.append('userName', state.form.userName)
formData.append('password', state.form.password)
formData.append('age', state.form.age)
formData.append('gender', state.form.gender)
formData.append('phoneNum', state.form.phoneNum)
formData.append('email', state.form.email)
formData.append('mbti', state.form.mbti)
formData.append('guide', state.form.guide)
formData.append('file', state.form.profileImg)
profileImg ({ commit }, payload) {
return axios
.post(`${BASE_URL}/api/v1/users`, payload,
{
headers: {
"Accept": "*/*",
"Content-Type": "multipart/form-data"
}
}
)
}
I tried #RequestPart MultipartFile file, but had the same error.
How can I fix it?
Sorry, I can't add comments, this answer is just my guess
what if you output
request.getHeader(HttpHeaders.CONTENT_TYPE);
Content-Type may have been changed if your request pass through Nginx or other agent
I found an answer here on GitHub
All you have to do is change
#RequestParam("file") MultipartFile file)
with :
#RequestParam("file") FilePart file)
I built a dummy api and I want to test it on swagger. The swagger.json has been successfully generated and executed to show the swagger UI.
But there is the 404 error that cannot find the response part.
How can I solve this?
This is the built swagger UI.
And this is the code.
#Service
#Api
public class className () {
#GET
#Path("/oauth2/authorize")
#Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
#Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
#ApiOperation(value = "Authorization Grant", notes = "Authorization Grant")
#ApiResponses(value = {
#ApiResponse(code = 200, message = "Successfully Granted the Authorization"),
#ApiResponse(code = 400, message = "Missing or invalid request body"),
#ApiResponse(code = 403, message = "Forbidden"),
#ApiResponse(code = 404, message = "Schema not found"),
#ApiResponse(code = 500, message = "Internal error")})
public Response authorizationGrant(
#HeaderParam("X-AUTH-TOKEN") final String token,
#HeaderParam("X-CSRF-TOKEN") final String csrftoken,
#ApiParam(value = "Client ID", required = true) #QueryParam("Client ID") final String clientId,
#ApiParam(value = "Scope", required = true) #QueryParam("Scope") final String scope,
#ApiParam(value = "Redirect Uri", required = true) #QueryParam("Redirect Uri") final String redirectUri,
#ApiParam(value = "Response Type", required = true) #QueryParam("Response Type") final String responseType ) throws AccessDeniedException {
return Response
.status(Response.Status.OK)
.entity("{\"hello\": \"This is a JSON response\"}")
.type(MediaType.APPLICATION_JSON)
.build();
}
}
Please tell me what you need more to be clear with this error.
The problem solved!!!
I hope this answer could help for others who are suffered from this trouble. :)
The error was from the #Api Definition part. I should have define the path in that part.
This is the corrected code.
#Path("/oauth2")
#Service
#Api
public class className () {
.....
#GET
#Path("/authorize")
.....
}
As you can see the #Api definition part requires the #Path annotation.
:)
as in the topic. I want to have different operations in swagger with same path and http method but with different content-type. Example:
I'm currently using Spring Boot in version 2.0.5 and Swagger ui in version 2.9.2.
In my API I have two methods to register user:
#RequestMapping(method = RequestMethod.POST, consumes = "application/customer+json", produces = MediaType.APPLICATION_JSON_VALUE)
#ApiOperation(value = "Registers a new application customer", notes = "Registers a new application customer.\n", response = CustomerResource.class)
#ApiResponses(value = {
#ApiResponse(code = 201, message = "Customer successfully registered"),
#ApiResponse(code = 409, message = "User with such email is already registered"),
#ApiResponse(code = 422, message = "Customer registration request contains validation errors. Response contains detailed field validation error message"),
#ApiResponse(code = 428, message = "Database error. Application log needs to be checked")})
public ResponseEntity<UserResource> registerCustomer(
#ApiParam(value = "Model representation of the transferred data to register a new customer") #Valid #RequestBody CustomerDto customerDto,
UriComponentsBuilder uriComponentsBuilder, BindingResult bindingResult)
{
...
}
and
#RequestMapping(method = RequestMethod.POST, consumes = "application/partner+json", produces = MediaType.APPLICATION_JSON_VALUE)
#ApiOperation(value = "Registers a new application partner", notes = "Registers a new Easy Parking partner.\n", response = PartnerResource.class)
#ApiResponses(value = {
#ApiResponse(code = 201, message = "Partner successfully registered"),
#ApiResponse(code = 409, message = "User with such email is already registered"),
#ApiResponse(code = 422, message = "Partner registration request contains validation errors. Response contains detailed field validation error message"),
#ApiResponse(code = 428, message = "Database error. Application log needs to be checked")})
public ResponseEntity<UserResource> registerPartner(
#ApiParam(value = "Model representation of the transferred data to register a new user") #Valid #RequestBody PartnerDto partnerDto,
UriComponentsBuilder uriComponentsBuilder, BindingResult bindingResult)
{ ... }
I want to have one POST path: /api/users to register two types of user: customer and partner. Two operations are required because partner has slightly different attributes than customer. I want to use content-type (consumes) to have different operations but swagger seems to work only with path and http method. Isn't it a bug?? Is there a way to configure it in Spring Boot Swagger?
I use swagger to create a RESTful API, and have several endpoints which return the same errors and responses:
#GET
#Path("/some/endpoint")
#ApiOperation(
value = "Some method",
notes = "Some method")
#ApiResponses(
value = {
#ApiResponse(code = 200, message = RestConstants.HTTP_200, response = Response.class),
#ApiResponse(code = 400, message = RestConstants.HTTP_400, response = Error.class),
#ApiResponse(code = 401, message = RestConstants.HTTP_401, response = Error.class),
#ApiResponse(code = 403, message = RestConstants.HTTP_403, response = Error.class),
#ApiResponse(code = 404, message = RestConstants.HTTP_404, response = Error.class),
#ApiResponse(code = 500, message = RestConstants.HTTP_500, response = Error.class)
})
public Response someMethod(){...}
The amount of #ApiResonses is may about to change. As of now, I need to declare all of theses for my individual endpoint methods.
Is there a way to use a constant value as an #ApiResponses value, e.g. like:
#ApiResponses(value = MY_RESPONSES)
Am I missing something?
This unfortunately isn't possible using the Swagger annotations.
For this to work ApiResponse would have to be a normal class/interface rather than an annotation.