Is there any way to test jersey #FormDataParam("file") FormDataBodyPart with postman.
I tried to hit below endpoint with postman
#POST
#Path("data/uploadPhoto")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadPhoto(#FormDataParam("file") FormDataBodyPart body) {
But postman is not reaching this endpoint
Related
In spring cloud gateway, added a filter that check for the authentication and authorization for further processing of request. I am calling authentication service using feign client, but I am getting the below error while invoking my service through spring cloud gateway.
java.lang.IllegalStateException: block()/blockFirst()/blockLast() are blocking, which is not supported in thread reactor-http-epoll-3\n\tat reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:83)\n\tSuppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: \nError has been observed at the following site(s):\n\t|_ checkpoint ⇢ org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter ....."
I would like to know is it wrong architecture I am using. How to proceed? I am stuck at this error.
#Autowired
private AuthenticationService authService;
// route validator
#Autowired
private RouterValidator routerValidator;
#Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
if (routerValidator.isSecured.test(request)) {
log.info("Accessing the restricted path");
if (this.isAuthMissing(request))
return this.onError(exchange, "Authorization header is missing in request", HttpStatus.UNAUTHORIZED);
final String token = this.getAuthHeader(request);
log.info("before authservice call");
AuthenticationResponse user = authService.isTokenValid(token);
log.info("after authservice call");
if (!user.isValid())
return this.onError(exchange, "Authorization header is invalid", HttpStatus.UNAUTHORIZED);
log.info("before calling populatedRequest");
this.populateRequestWithHeaders(exchange, user);
}
return chain.filter(exchange);
}
private Mono<Void> onError(ServerWebExchange exchange, String err, HttpStatus httpStatus) {
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(httpStatus);
return response.setComplete();
}
private String getAuthHeader(ServerHttpRequest request) {
return request.getHeaders().getOrEmpty("Authorization").get(0);
}
private boolean isAuthMissing(ServerHttpRequest request) {
log.info("inside auth missing");
return !request.getHeaders().containsKey("Authorization");
}
private void populateRequestWithHeaders(ServerWebExchange exchange, AuthenticationResponse authRes) {
log.info("About to mutate the request->{}",exchange);
exchange.getRequest().mutate()
.header("id",Integer.toString(authRes.getUserId()))
.build();
}
Feign interface
#Autowired
private AuthenticationFeign auth;
public AuthenticationResponse isTokenValid(String token) {
return auth.getValidity(token);
}
I couldn't clearly read it. But problem is that: you can not make blocking call in filter pipeline. Current reactive impl. is like that. if you want, u can use .then() method of WebClient. U should use webclient. because it's reactive.
this link may help you:
https://github.com/spring-cloud/spring-cloud-gateway/issues/980
There was a long time, but i want to give answer. I hope, this help u, please response back, it works or not.
When I enable http trace in SpringBoot application (https://stackoverflow.com/a/59115579/6700081) then using the /httptrace endpoint I am able to view all the requests (only headers. not request body) that hit the application.
Is it possible to also view all the requests sent out from the application to other applications like Rest services, webservices, etc in /httptrace endpoint?
I want to know what are all the external services that my application is connecting to, when I send a particular request to the application
if you are using RestTemplate for your Rest call, then you can add an ClientHttpRequestInterceptor as suggested by gtiwari333.
public class LoggingInterceptor implements ClientHttpRequestInterceptor {
static Logger log = LoggerFactory.getLogger(LoggingInterceptor.class);
#Override
public ClientHttpResponse intercept(HttpRequest req, byte[] reqBody, ClientHttpRequestExecution ex)
throws IOException {
log.debug("Request body: {}", new String(reqBody, StandardCharsets.UTF_8));
ClientHttpResponse response = ex.execute(req, reqBody);
InputStreamReader isr = new InputStreamReader(response.getBody(), StandardCharsets.UTF_8);
String body = new BufferedReader(isr)
.lines()
.collect(Collectors.joining("\n"));
log.debug("Response body: {}", body);
return response;
}
}
i'm working on a spring boot project where i should call a rest api using Feign via Spring Cloud, i can call the rest api using feignClient without any problem,
now the rest api that i call needs a JWT to let me consume it, to send a JWT from my code i used RequestInterceptor and this my code :
class AuthInterceptor implements RequestInterceptor {
#Override
public void apply(RequestTemplate template) {
template.header("Authorization", "Bearer eyJraWQiOiJOcTVZWmUwNF8tazZfR3RySDZkenBWbHhkY1uV_1wSxWPGZui-t1Zf2BkbqZ_h44RkjVtQquIe0Yz9efWS6QZQ");
}
}
i put manually the JWT in the code and this work fine ...
my issue is : the JWT expire after 30 min and i should call manually another rest api that generate a JWT then i hardcode it in my code...
my question is : there any solution to call programmatically the api that generate JWT then inject this JWT in the Interceptor?
Thanks in advance.
Best Regards.
Get the Token from the current HttpServletRequest header.
public void apply(RequestTemplate template) {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes())
.getRequest();
String jwtToken = request.getHeader(HttpHeaders.AUTHORIZATION);
if (jwtToken != null) {
template.header(HttpHeaders.AUTHORIZATION, jwtToken);
}
}
How to correctly implement restTemplate with authorisation token?
I have a Zuul gateway which passes a JWT downstream to other services correctly, assuming I don't want to do anything on the gateway first, using a config like:
zuul:
sensitive-headers:
routes:
instance-service:
path: /instances/**
strip-prefix: false
And using a token relay filter:
#Component
public class TokenRelayFilter extends ZuulFilter {
#Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
Set<String> headers = (Set<String>) ctx.get("ignoredHeaders");
headers.remove("authorization");
return null;
}
#Override
public boolean shouldFilter() {
return true;
}
#Override
public String filterType() {
return "pre";
}
#Override
public int filterOrder() {
return 10000;
}
}
Which just forwards everything to the instance-service, works a treat.
However if I remove the routes config from the config.yml file because I want to handle some things on the gateway before manually calling the service I loose the access token and get a 401 back from the downstream services
#ApiOperation(value = "List all instances and their properties.")
#GetMapping("/instances")
public ResponseEntity<String> instances() {
ParameterizedTypeReference<String> reference = new ParameterizedTypeReference<String>() {
};
return restTemplate.exchange("http://instance-service", HttpMethod.GET, null, reference);
}
My RestTemplate is just wired up generically
#Configuration
public class MyConfiguration {
#LoadBalanced
#Bean
RestTemplate restTemplate() {
return new RestTemplate();
}
}
How do I correctly get the JWT back into the new RestTemplate without having to manually create and add a header in each request?
Am I supposed to be using OAuth2RestTemplate?
After some discussion, it seems like you have two options:
Implement and endpoint and dig the Auth header out via #RequestParam on request. From there, you can add it back on for the subsequent outbound request via RestTemplate to your downstream service.
Use Zuul to proxy your request (Auth header included, make sure its excluded from the sensitive-headers config) and implement a pre filter to include any additional logic you might need.
If I had to pick, it sounds like something Zuul should be doing since it's likely acting as your gateway for both your queue and other services, and it looks like you are trying to implement a proxy request, which Zuul can already do, but it's tough to say without knowing the full scope of the architecture.
I have created a basic REST controller which makes requests using the reactive Webclient in Spring-boot 2 using netty.
#RestController
#RequestMapping("/test")
#Log4j2
public class TestController {
private WebClient client;
#PostConstruct
public void setup() {
client = WebClient.builder()
.baseUrl("http://www.google.com/")
.exchangeStrategies(ExchangeStrategies.withDefaults())
.build();
}
#GetMapping
public Mono<String> hello() throws URISyntaxException {
return client.get().retrieve().bodyToMono(String.class);
}
}
When I get a 3XX response code back I want the webclient to follow the redirect using the Location in the response and call that URI recursively until I get a non 3XX response.
The actual result I get is the 3XX response.
You need to configure the client per the docs
WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(
HttpClient.create().followRedirect(true)
))
You could make the URL parameter of your function, and recursively call it while you're getting 3XX responses. Something like this (in real implementation you would probably want to limit the number of redirects):
public Mono<String> hello(String uri) throws URISyntaxException {
return client.get()
.uri(uri)
.exchange()
.flatMap(response -> {
if (response.statusCode().is3xxRedirection()) {
String redirectUrl = response.headers().header("Location").get(0);
return response.bodyToMono(Void.class).then(hello(redirectUrl));
}
return response.bodyToMono(String.class);
}