Unbale to prevent PROPFIND http-method from servelt filter - servlet-filters

I have made a filter and register on web.xml
when i am trying to filter http request of PROPFIND its throwing 500 Internal server error . this code works fine for any other http-methods. I want to have 405 in response code
if (httpRequest.getMethod()==”PROPFIND”) {
HttpServletResponse respProp = (HttpServletResponse) response;
respProp.sendError(405);
chain.doFilter(request, respProp);
} else {
chain.doFilter(request, response);
error i am getting
java.lang.IllegalStateException: Cannot call sendError() after the response has been committed
at org.apache.catalina.connector.ResponseFacade.sendError(ResponseFacade.java:462)
at javax.servlet.http.HttpServletResponseWrapper.sendError(HttpServletResponseWrapper.java:120)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:673)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812)

Instead of sending error i have sent 405 as response and my problem got solved
if (httpRequest.getMethod()==”PROPFIND”) {
HttpServletResponse resp = (HttpServletResponse) response;
resp.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
} else {
chain.doFilter(request, response);
}

Related

Spring Cloud API Gateway Custom Filters with external API for Authorization

I have a spring cloud gateway app with a custom filter to do Authorization in a route.
The route target is a blocking api also.
The Authorization filter fetches the permissions of the users from an external auth api using jwt token (blocking).
Then I am trying to check if the required permission is there , if not throw 401 .
But I am not getting the expected result as I am not able to figure how to handle the Mono from the permissions API.
The response is 200 even if the authorization is failing .
If the Authorization is allowed then I get the proper response from the downstream api in route.
Filter Code
#Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
ServerHttpRequest request = exchange.getRequest();
String authorizationHeader = request.getHeaders().get(HttpHeaders.AUTHORIZATION).get(0);
//API to get permissions
Mono<PermissionResponse> permissionsOfUser = getPermissions(authorizationHeader);
return permissionsOfUser.flatMap(pu->{
//doing permission check
if(!isAuthorized(pu)){
return Mono.error(new AuthorizationException("Invalid"));
}else {
return chain.filter(exchange);
}
})
.doOnError(auth->this.onError(exchange,HttpStatus.UNAUTHORIZED))
.doOnNext(auth->chain.filter(exchange));
};
}
Authorization Check
private boolean isAuthorized(PermissionResponse permissionResponse) {
if(permissionResponse.getFunctions().stream().map(f->f.getFuncKey()).collect(Collectors.toList()).contains("EDIT_ACCESS")){
log.info("Has Permissions");
return true;
}else{
log.info("No Permissions");
return false;
}
}
API Call to get permissions
private Mono<PermissionResponse> getPermissions(String authorizationHeader) {
return webClientBuilder.build()
.get()
.uri(authPermissionsUrl)
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.header(HttpHeaders.AUTHORIZATION, authorizationHeader)
.retrieve()
.bodyToMono(PermissionResponse.class)
.subscribeOn(Schedulers.immediate())
.publishOn(Schedulers.immediate());
}
Error Response
private Mono<Void> onError(ServerWebExchange exchange, HttpStatus httpStatus) {
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(httpStatus);
return response.setComplete();
}
Routing
cloud:
gateway:
default-filters:
- name: CustomAuthorizationFilter
routes:
- id: app-id
uri: http://myapi.com
predicates:
- Path=/getMyApiDetails/**
My thought is that I am not properly consuming the permission API Mono and not able to return the error from the filter.
I am new to webflux and not sure how to properly chain this.
log
2022-08-26 10:22:03.314 ERROR 16068 --- [ctor-http-nio-5] o.s.w.s.adapter.HttpWebHandlerAdapter : [a7062490-6] 500 Server Error for HTTP GET "/getMyApiDetails/getDetails"
com.gateway.config.AuthorizationException: Invalid
at com.gateway.filters.CustomAuthorizationFilter.lambda$apply$0(CustomAuthorizationFilter.java:60) ~[classes/:na]
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
Original Stack Trace:
at
com.gateway.filters.CustomAuthorizationFilter.lambda$apply$0(CustomAuthorizationFilter.java:60) ~[classes/:na]
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:125) ~[reactor-core-3.4.19.jar:3.4.19]
at reactor.core.publisher.MonoPublishOn$PublishOnSubscriber.run(MonoPublishOn.java:181) ~[reactor-core-3.4.19.jar:3.4.19]

Why is Axios sending an extra 204 preflight request with my POST request?

Whenever I send a POST request using Vue.js (3.x), an additional request to the same URL is being made with HTTP status code 204 & type of "preflight".
What is this preflight request and how can I fix it so it isn't sent as a duplicate?
Register.vue
async submit() {
this.button = true;
try {
const response = await axios.post(`register`, this.form);
if(response.data.success == false)
{
console.log(response.data.message);
}
else
{
this.$router.push('/');
}
}
catch (error)
{
let { errors } = error.response.data;
this.button = false;
this.errors = {};
Object.keys(errors).forEach(element => {
this.errors[element] = errors[element][0];
});
}
},
This is not an issue and is controlled by the browser by design.
It is not something Axios or any other HTTP client decides to send.
A preflight request is a CORS OPTIONS request & are automatically sent by browsers specifically to check if the server would support the call you are trying to make in terms of method, headers and origin.
You can safely ignore the requests if they do not fail as that means that the server will not be rejecting your request on the basis of the aforementioned factors.
Your issue relates to the endpoint not existing as you are getting a 404 Not Found error - check to see if the endpoint exists or if you are calling it correctly.

PostMan is working but http is giving 404 error in flutter

I am using following code for my api. This api is working in postman but showing 404 error code in http flutter.
My flutter code:
RaisedButton(
onPressed: () {
apiCall();
},
child: Text("Press"),
)
Future apiCall() async {
var body =
jsonEncode({"filepath": "patient/reports/1602333458533-Liver.jpg"});
try {
await http
.post('http://3.6.197.52:3100/downloadFile',
headers: {"Accept": "Application/json"}, body: body)
.then((http.Response response) => print(response.statusCode));
} catch (e) {
print(e);
}
}
It is giving error code 404 .
Following is postman result:
Post Man result
You are setting the wrong headers. The Accept header is for determining which result type you expect from the server. From your screenshot (and the data) it seems quite clear, you would expect an image/jpg. On the other hand, you are missing the Content-Type header, which defines what type of data you are sending with your request, in your case application/json. So the server probably can't parse the body correctly.
Assuming, that jsonEncode is just something like JSON.stringify you should do something like the following
Future apiCall() async {
var body =
jsonEncode({"filepath": "patient/reports/1602333458533-Liver.jpg"});
try {
await http
.post('http://3.6.197.52:3100/downloadFile',
headers: {"Content-Type": "application/json"}, body: body)
.then((http.Response response) => print(response.statusCode));
} catch (e) {
print(e);
}
}

only http status been caught and not the JSON error response

The backend API responds with HTTP Status 400 and error messages as follows:
{detail: 'msg'}
It works well on web portal but with the following code, I can't read the response data:
try {
let res = await axios.post(APIS.START.LOGIN, loginData);
} catch (e) {
console.log(69, e);
}
You can access the body of the failed request by referencing e.response.data.
Simply replace console.log(69, e) with console.log(69, e.response.data)

Log middle-ware gets 200 response code when it is actually a 500

I am working on a ASP.Net Core Web API project and I want to log all the requests and 500 server errors.
I used custom middleware to log requests, and it is defined in the startup.cs as:
app.UseMiddleware<logMiddleware>();
I also defined an Exception handler to capture server errors in the startup.cs:
app.UseExceptionHandler(builder => {
builder.Run(async context => {
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
var error = context.Features.Get<IExceptionHandlerFeature>();
if (error != null) {
logService logger = new logService(conf);
await logger.logError(error, context);
}
});
});
I keep the request information in error logs, so I don't need to save the request log when the response code is 500, so I added a check into request log function to filter errors:
public async Task logRequestAsync(HttpContext context) {
if (context.Response.StatusCode != 500) {
//do things
}
}
The problem is the Response.StatusCode returns as 200 instead of 500. Probably it runs before the API call's function is completed and the server error happens later in the runtime.
Is there a way to move the "request log" process to the point where the response is created instead of the beginning of the API request?