Spring cloud api gateway not sending POST request correctly - java

I have two applications
a. monolith (developed with java servlet)
b. Spring boot microservice (in development)
I am trying to develop spring cloud api gateway which will sit infront of this two apps and will serve the traffic based on what request it receives. Mostly both apps support POST method and routing in api gateway works fine for b.spring boot microservice but when same request and url I tried on monolith its been observed that spring cloud api gateway sending GET request (which is not allowed ) and getting failed with 404 error. Is there any way to identify what exact request api gateway tried ? OR does api gateway try first GET and then POST ?
I am able to confirm that I am receiving GET request on the POST request that I tried on api gateway by checking the access logs
0:0:0:0:0:0:0:1 - - [14/Jul/2022:12:34:31 -0700] "**GET** /myservice/revers HTTP/1.1" 404 1685 "PostmanRuntime/7.29.0" "0/455"
logs from api gateway after enabling the TRACE
2022-07-15 01:04:30.426 INFO 16016 --- [ctor-http-nio-3] c.t.tes.gwapi.config.LoggingFilter : Incoming request http://localhost:8080/servlet ,is routed uri:http://10.2.1.55:3068/myservice/revers with id: my-route-id
2022-07-15 01:04:31.665 DEBUG 16016 --- [ctor-http-nio-3] r.netty.http.client.HttpClientConnect : [d95e4f2a-1, L:/10.01.57.01:59773 - R:/10.2.1.55:3068] Handler is being applied: {uri=http://10.2.1.55:3068/myservice/revers , method=POST}
2022-07-15 01:04:31.974 DEBUG 16016 --- [ctor-http-nio-3] r.n.http.client.HttpClientOperations : [d95e4f2a-1, L:/10.01.57.01:59773 - R:/10.2.1.55:3068] Received response (auto-read:false) : [Date=Thu, 14 Jul 2022 19:34:31 GMT, Server=Apache, Last-Modified=Wed, 06 Jul 2022 09:15:29 GMT, Accept-Ranges=bytes, Content-Type=text/html, content-length=1685]
2022-07-15 01:04:31.983 DEBUG 16016 --- [ctor-http-nio-3] r.n.http.client.HttpClientOperations : [d95e4f2a-1, L:/10.01.57.01:59773 - R:/10.2.1.55:3068] Received last HTTP packet
2022-07-15 01:04:31.987 INFO 16016 --- [ctor-http-nio-3] c.t.t.gwapi.config.SpringCloudConfig : Response body <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
sample html
Here is sample api config
#Bean
public RouteLocator myRouteSavingRequestBody(RouteLocatorBuilder builder) {
return builder.routes()
.route("my-route-id",
p -> p
.path("/servlet/**") //your own path filter
.filters(f -> f
.modifyResponseBody(String.class, String.class,
(webExchange, originalBody) -> {
if (originalBody != null) {
//log.info("Response body {}", originalBody);
return Mono.just(originalBody);
} else {
return Mono.empty();
}
})
.modifyRequestBody(String.class, String.class,
(webExchange, originalBody) -> {
if (originalBody != null) {
// log.info("Request body {}", originalBody);
return Mono.just(originalBody);
} else {
return Mono.empty();
}
})
.setPath("/myservice/revers")
)
.uri("http://10.2.1.55:3068")
)
.build();
}

Related

adding request id in request using MDC in zuul gateway service doesn't reflect client micro service application

I have written a Pre filter in zuul gateway
#Override
public Object run() throws ZuulException
{
String uniqueID = UUID.randomUUID().toString();
MDC.put("request_id", uniqueID);
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
request.setAttribute("request_id", uniqueID);
//requestContext.set("request_id", uniqueID);
logger.info("request-id generated is => {}", uniqueID);
logger.info("Pre Filter => "+ String.format("%s request to %s", request.getMethod(), request.getRequestURL().toString()));
// MDC.clear();
return null;
}
Zuul gateway logs -> request Id added and appended in logs
2022-08-22 01:57:00.283+0200 [http-nio-8080-exec-6] INFO [] c.h.z.ZuulGatewayApplication$MyFilter - BEFORE
2022-08-22 01:57:00.284+0200 [http-nio-8080-exec-6] INFO [f40d9b07-c33f-4996-bb3a-b16df3ba6436] c.h.z.filter.MDCLoggingPreFilter - request-id generated is => f90447a5-974d-4c38-beba-377addce446c
2022-08-22 01:57:00.284+0200 [http-nio-8080-exec-6] INFO [f40d9b07-c33f-4996-bb3a-b16df3ba6436] c.h.z.filter.MDCLoggingPreFilter - Pre Filter => GET request to http://localhost:8080/home
2022-08-22 01:57:00.285+0200 [http-nio-8080-exec-6] INFO [f40d9b07-c33f-4996-bb3a-b16df3ba6436] c.h.z.f.MDCLoggingPreFilter2 - Pre Filter 2 => GET request to http://localhost:8080/home
2022-08-22 01:57:00.297+0200 [http-nio-8080-exec-6] INFO [f40d9b07-c33f-4996-bb3a-b16df3ba6436] c.h.z.f.MDCLoggingPostFilter - Post Filter => GET request to http://localhost:8080/home
2022-08-22 01:57:00.298+0200 [http-nio-8080-exec-6] INFO [f40d9b07-c33f-4996-bb3a-b16df3ba6436] c.h.z.f.MDCLoggingPostFilter2 - Post Filter 2=> GET request to http://localhost:8080/home
2022-08-22 01:57:00.299+0200 [http-nio-8080-exec-6] INFO [f40d9b07-c33f-4996-bb3a-b16df3ba6436] c.h.z.ZuulGatewayApplication$MyFilter - AFTER
Screenshot
but when the request forwards to client application , there is no request Id
2022-08-22 01:57:00.287+0200 [http-nio-8081-exec-3] INFO [] c.h.z.controller.HomeController - simple get method
Screen Shot For Client microservice

Authentication issue with spring security, JWT on resource API

I am having a issue related to authentication where I am getting logged out of my app when trying to GET from an endpoint that was created from a POST (HTTTP STATUS 201) I see the following errors. The backend is seeing the user as anonymousUser while I am logged in but works fine for another endpoint in the same file :
2018-10-22 11:33:35.251 DEBUG 2124 --- [ XNIO-8 task-23]
c.c.link.aop.logging.LoggingAspect : Enter:
org.springframework.boot.actuate.audit.AuditEventRepository.add() with
argument[s] = [AuditEvent [timestamp=Mon Oct 22 11:33:35 PDT 2018,
principal=anonymousUser, type=AUTHORIZATION_FAILURE,
data={details=org.springframework.security.web.authentication.WebAuthenticationDetails#fffed504:
RemoteIpAddress: 127.0.0.1; SessionId:
_5aP-S8x27gGSIjtbkR6EwrWOD9Yybnd-4M3z0ol, type=org.springframework.security.access.AccessDeniedException,
message=Access is denied}]] 2018-10-22 11:33:35.258 DEBUG 2124 --- [
XNIO-8 task-23] c.c.link.aop.logging.LoggingAspect : Exit:
org.springframework.boot.actuate.audit.AuditEventRepository.add() with
result = null 2018-10-22 11:33:35.343 WARN 2124 --- [ XNIO-8 task-23]
o.z.p.spring.web.advice.AdviceTrait : Unauthorized: Full
authentication is required to access this resource
The same resource (DeliveryResource.java) has an endpoint that works fine
the only difference between both end points is one is /getList (this one is working fine) VS. /getPackingListReport/{number} (this one fails authentication).
The API definitions are shown below:
#GetMapping("/getPackingListReport/{number}")
#Secured(AuthoritiesConstants.USER)
#Timed
public ArrayList<WebOrder> getPackingListReportFromDB(#PathVariable("number") long packingListNbr)
vs.
#GetMapping("/getList")
#Secured(AuthoritiesConstants.USER)
#Timed
public WebOrder getList(#RequestParam(value = "custid") long custid,#RequestParam(value = "pId") long pId) {
I found the problem.
I was using the following for the "/getList" mapping:
// call dao to insert to DB the list and then call the stored proc
URI location = ServletUriComponentsBuilder.fromCurrentContextPath().path("/api/rest/getPackingListReport/{packingListNumber}").buildAndExpand(packingListNumber).toUri();
return ResponseEntity.created(location).build();
to return a created resource URI (HTTP STATUS 201) after a POST. That path contained the incorrect URI starting with , "http://localhost" when jHipster is currently default set to only handle and look for "/api" or in my case i added "/rest/api/*" on the Angular5 side.
I fixed the issue by filtering out any characters before "/api/" after receiving the URL.

HTTP Status 404 The requested resource is not available - springMVC

I'm building spring mvc application with spring security.
This is my url :
http://localhost:8080/inbalUI/login
And I'm getting to my controller :
#RequestMapping(value = "/login", method = RequestMethod.GET)
public String loginPage() {
if (isCurrentAuthenticationAnonymous()) {
return "login";
} else {
return "login";
// return "redirect:/list";
}
}
This is the log :
20:02:10.823 [http-nio-8080-exec-10] DEBUG org.springframework.web.servlet.view.JstlView - Forwarding to resource [/WEB-INF/views/login.jsp] in InternalResourceView 'login'
20:02:10.825 [http-nio-8080-exec-10] DEBUG org.springframework.security.web.context.HttpSessionSecurityContextRepository - SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
20:02:10.825 [http-nio-8080-exec-10] DEBUG org.springframework.web.servlet.DispatcherServlet - Successfully completed request
20:02:10.825 [http-nio-8080-exec-10] DEBUG org.springframework.security.web.access.ExceptionTranslationFilter - Chain processed normally
20:02:10.825 [http-nio-8080-exec-10] DEBUG org.springframework.security.web.context.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed
This is the login.jsp deploying path on tomcat :
C:\me\apache\apache-tomcat-8.0.36\webapps\inbalUI\WEB-INF\classes\WEB-INF\views
But I'm getting HTTP Status 404:
HTTP Status 404 - /inbalUI/WEB-INF/views/login.jsp
type Status report
message /inbalUI/WEB-INF/views/login.jsp
description The requested resource is not available.
Apache Tomcat/8.0.36
Any idea why ?
It seems to me that you use the wrong folder for views.
According to this article https://vitalflux.com/web-application-folder-structure-spring-mvc-web-projects/ this folder should be at:
src/WEB-INF/views/login.jsp
and you probably put it under
src/resources/WEB-INF/views/login.jsp
Which results in WEB-INF/views/login.jsp being put into the classpath (classes/WEB-INF/views/login.jsp)

Spring integration dsl: http outbound gateway

Faced spring integration java-dsl issue, I'm stuck. This is a code I have for my flow declaration:
#Bean
public IntegrationFlow orchestrationFlow() {
return IntegrationFlows.from(
Jms.messageDrivenChannelAdapter(queueConnectionFactory())
.destination(bookingQueue())
.outputChannel(bookingChannel()))
.<String, BookingRequest>transform(s -> {
Ticket t = new Gson().fromJson(s, Ticket.class);
return new BookingRequest()
.setMovieId(t.getMovie().getId())
.setRow(t.getSeat().getRow())
.setSeat(t.getSeat().getNumber())
.setScreenNumber(t.getScreenNumber()
);
})
// HTTP part goes here
.<BookingRequest, HttpEntity>transform(HttpEntity::new)
.handle(
Http.outboundChannelAdapter(bookingServerUrl)
.httpMethod(HttpMethod.POST)
.extractPayload(true)
.expectedResponseType(BookStatus.class)
)
// and here HTTP part ends
.handle(
Jms.outboundAdapter(responseDestinationTemplate())
)
.get();
}
And everything was OK until I utilized HTTP outbound channel adapter. I need to call simple RESTful interface and code above does it pretty well. But, following Jms.outboundAdapter(responseDestinationTemplate()) line leads to nothing, no action performes after successfull http call.
If I remove http flow part (surrounded by comments) - it works. Implemented so much stuff, almost understood and saw beauty and simplicity of integration ...aand this is it. Yet another place I got stuck in.
And here are log after success REST call:
2016-02-08 21:01:22.155 DEBUG 18209 --- [enerContainer-1] o.s.web.client.RestTemplate : POST request for "http://localhost:9052/api/book" resulted in 200 (OK)
2016-02-08 21:01:22.156 DEBUG 18209 --- [enerContainer-1] o.s.web.client.RestTemplate : Reading [class c.e.m.integration.domain.BookStatus] as "application/json;charset=UTF-8" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter#6b9469bd]
2016-02-08 21:01:22.168 DEBUG 18209 --- [enerContainer-1] i.h.o.HttpRequestExecutingMessageHandler : handler 'org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler#0' produced no reply for request Message: GenericMessage [payload=<BookingRequest(movieId=0, row=1, seat=1, screenNumber=1),{}>, headers={jms_redelivered=false, jms_replyTo=queue://statusChannel, jms_correlationId=5021291a-d4d5-47ca-b591-b6f311378688, correlationId=1d41f05a-3695-4adb-87b0-d75c17bbc3ad, id=a1fb2a2f-5d78-3183-d409-3f60aae74a20, priority=4, jms_timestamp=1454950877264, jms_messageId=ID:ins-laptop-31198-1454948247657-1:9:1:1:1, timestamp=1454950877352}]
2016-02-08 21:01:22.168 DEBUG 18209 --- [enerContainer-1] o.s.integration.channel.DirectChannel : postSend (sent=true) on channel 'inboundFlow.channel#2', message: GenericMessage [payload=<BookingRequest(movieId=0, row=1, seat=1, screenNumber=1),{}>, headers={jms_redelivered=false, jms_replyTo=queue://statusChannel, jms_correlationId=5021291a-d4d5-47ca-b591-b6f311378688, correlationId=1d41f05a-3695-4adb-87b0-d75c17bbc3ad, id=a1fb2a2f-5d78-3183-d409-3f60aae74a20, priority=4, jms_timestamp=1454950877264, jms_messageId=ID:ins-laptop-31198-1454948247657-1:9:1:1:1, timestamp=1454950877352}]
2016-02-08 21:01:22.168 DEBUG 18209 --- [enerContainer-1] o.s.integration.channel.DirectChannel : postSend (sent=true) on channel 'inboundFlow.channel#1', message: GenericMessage [payload=BookingRequest(movieId=0, row=1, seat=1, screenNumber=1), headers={jms_redelivered=false, jms_replyTo=queue://statusChannel, jms_correlationId=5021291a-d4d5-47ca-b591-b6f311378688, correlationId=1d41f05a-3695-4adb-87b0-d75c17bbc3ad, id=859af23d-214f-4400-e9cb-7d40308755cd, priority=4, jms_timestamp=1454950877264, jms_messageId=ID:ins-laptop-31198-1454948247657-1:9:1:1:1, timestamp=1454950877350}]
2016-02-08 21:01:22.168 DEBUG 18209 --- [enerContainer-1] o.s.integration.channel.DirectChannel : postSend (sent=true) on channel 'inboundFlow.channel#0', message: GenericMessage [payload={"screenNumber":1,"seat":{"row":1,"number":1},"movie":{"id":0,"name":"The Matrix"}}, headers={jms_redelivered=false, jms_replyTo=queue://statusChannel, jms_correlationId=5021291a-d4d5-47ca-b591-b6f311378688, correlationId=1d41f05a-3695-4adb-87b0-d75c17bbc3ad, id=636638ed-aec2-082e-6181-0484999fd807, priority=4, jms_timestamp=1454950877264, jms_messageId=ID:ins-laptop-31198-1454948247657-1:9:1:1:1, timestamp=1454950877331}]
No errors, no warnings at all.
Spring Integration provides two MessageHandler types: one-way - just handle message and stop. And another one is like: handle request message and produce reply to the output channel.
The first one is called like outboundChannelAdapter and with your HTTP case you just only send a POST request and don't worry about the reply.
Since the message flow is stopped on the outboundChannelAdapter no any further action is possible in the integration chain. Like in your case the next Jms.outboundAdapter won't be reached.
If you really expect the reply from your REST service you should use Http.outboundGateway instead. And your BookStatus will be sent to the JMS as you'd like by your last .handle() in the flow.

spring oauth obtain user details from token

i want to use spring and oauth and so far it seemed to work.
now i added a zuul proxy that is configured like that:
spring:
oauth2:
sso:
home:
secure: false
path: /,/**/*.html
client:
accessTokenUri: http://${authserver.hostname}:${authserver.port}/${authserver.contextPath}/oauth/token
userAuthorizationUri: http://${authserver.hostname}:${authserver.port}/${authserver.contextPath}/oauth/authorize
clientId: webapp
clientSecret: secret
resource:
id: apis
userInfoUri: http://${authserver.hostname}:${authserver.port}/${authserver.contextPath}/rest/me
preferTokenInfo: false
whenever i try to access an resource server it tries to verify my authentication but my authserver endpoint seems to return text/html instead of json.
Created GET request for "http://localhost:8091/userauth/rest/me"
2015-11-24 14:07:12.275 DEBUG 3601 --- [nio-8080-exec-3] o.s.s.oauth2.client.OAuth2RestTemplate : Setting request Accept header to [application/json, application/*+json]
2015-11-24 14:07:12.287 DEBUG 3601 --- [nio-8080-exec-3] o.s.s.oauth2.client.OAuth2RestTemplate : GET request for "http://localhost:8091/userauth/rest/me" resulted in 200 (OK)
2015-11-24 14:07:12.288 INFO 3601 --- [nio-8080-exec-3] o.s.c.s.o.r.UserInfoTokenServices : Could not fetch user details: class org.springframework.web.client.RestClientException, Could not extract response: no suitable HttpMessageConverter found for response type [interface java.util.Map] and content type [text/html;charset=UTF-8]
i already forced json and when accessing auth server directly via curl i get json formatted principal.
#RequestMapping(value="/me", produces = "application/json")
public Principal getCurrentLoggedinUser(Principal user){
return user;
}
any ideas how to send json to my zuul proxy so it can verify my authentication?

Categories