Reputation: 319
I have a spring boot app with an HTTP
post
request handler. I want to make it so that when I use the following curl command:
curl -d "ncs|56-2629193|1972-03-28|20190218|77067|6208|3209440|self|-123|-123|-123|0.0|0.0|0.0|0.0|0.0|0.0|0.0"
-H 'Content-Type: text/plain' 'http://localhost:9119/prediction'
I don't have to add the header content type.
this is my code:
@RequestMapping(value = "/prediction", method = RequestMethod.POST, produces = {"application/json"},consumes= "text/plain")
public ResponseEntity<String> payloader(@RequestBody String params ) throws IOException{
LinkedHashMap<String,String> x = mockconfig.getHM();
String[] a = params.split("\\|");
if(a.length!=18){
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Requires 18 parameters");
}
if(params.equals((String) x.keySet().toArray()[0])) {
return ResponseEntity.ok(x.get(mockconfig.input1));
}
else if(params.equals((String) x.keySet().toArray()[1])) {
return ResponseEntity.ok(x.get(mockconfig.input2));
}
else if(params.equals((String) x.keySet().toArray()[2])) {
return ResponseEntity.ok(x.get(mockconfig.input3));
}
else if(params.equals((String) x.keySet().toArray()[3])) {
return ResponseEntity.ok(x.get(mockconfig.input4));
}
else {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Inccorect payload");
}
}
}
I set it so it consumes text/plain but I still need to add the header in the curl command or it throws this error:
"status":415,"error":"Unsupported Media Type","message":"Content type 'application/x-www-form-urlencoded' not supported","path":"/prediction"
Any workaround?
I have tried using content negotiator and created this class
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.defaultContentType(MediaType.TEXT_PLAIN);
}
}
But this just caused to throw errors in the java console:
.w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/x-www-form-urlencoded' not supported]
.w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation]
and wouldn't return anything in terminal when curling.
Adding this dependency into my pom.xml:
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformats-text</artifactId>
<version>2.10.0.pr1</version>
<type>pom</type>
</dependency>
also didn't get it to work...
EDIT: I changed my code to what Madhu recommended:
@PostMapping(value = "/prediction")
public ResponseEntity<String> payloader(@RequestBody String params ) throws IOException{
LinkedHashMap<String,String> x = mockconfig.getHM();
a = params.split("\\|"); //line 35
if(a.length!=18){
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Requires 18 parameters");
}
if(params.equals((String) x.keySet().toArray()[0])) {
return ResponseEntity.ok(x.get(mockconfig.input1));
}
else if(params.equals((String) x.keySet().toArray()[1])) {
return ResponseEntity.ok(x.get(mockconfig.input2));
}
else if(params.equals((String) x.keySet().toArray()[2])) {
return ResponseEntity.ok(x.get(mockconfig.input3));
}
else if(params.equals((String) x.keySet().toArray()[3])) {
return ResponseEntity.ok(x.get(mockconfig.input4));
}
else {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Inccorect payload");
}
}
and when I do the curl without header it responds with my response entity status
"Requires 18 parameters"
But when I add the header to the same curl command it spits out the JSON successfully.
The parameters are the same though.
Upvotes: 1
Views: 2396
Reputation: 15213
If you use consumes= "text/plain"
in your controller method, you would have to pass the content-type header as part of the curl request. Simple way would be to have your controller method as below:
@PostMapping(value = "/prediction")
public ResponseEntity<String> payloader(@RequestBody String params ) throws IOException{
//method implementation
}
Then you can use the curl as
curl -d "ncs|56-2629193|1972-03-28|20190218|77067|6208|3209440|self|-123|-123|-123|0.0|0.0|0.0|0.0|0.0|0.0|0.0" http://localhost:9119/prediction
UPDATE: With reference to this documentation:
POSTing with curl's -d option will make it include a default header that looks like
Content-Type: application/x-www-form-urlencoded
.
So when you don't pass the Content-Type
header in the curl, it would result in sending the application/x-www-form-urlencoded
content-type by curl. Hence it would encode the string, replacing the |
as below:
ncs%7C56-2629193%7C1972-03-28%7C20190218%7C77067%7C6208%7C3209440%7Cself%7C-123%7C-123%7C-123%7C0.0%7C0.0%7C0.0%7C0.0%7C0.0%7C0.0%7C0.0=
which would mean that your split regex wouldn't work. So you MUST either send Content-Type: text/plain
in the curl, or just Content-Type:
which would even work. So the issue that you are facing is with how curl works by default, rather than your java code.
Upvotes: 2