I defines a route with attribute<"id", "demo">:
route(GET("/demo").and(accept(MediaType.APPLICATION_JSON)), handler::handle)
.withAttribute("id", "demo")
In the handler funaction, how can I obtain the above defined attribute?
public Mono<ServerResponse> handle(ServerRequest serverRequest) {
// Here, how to get the attribute<id, demo> ?
}
Related
I have an application implemented using Spring WebFlux, and the routing is done through RouterFunctions. Now I want the controller selection to be based on some customized class dynamically in runtime instead of just static URI pattern or request header, how to do that?
For example: there is a request with path /v1/xyz, today we want to have 60% random requests with that path go to controller A and 40% go to controller B, and tomorrow the percentage will be adjusted to 80% and 20%. So I need a mechanism to dynamically decide which controller the same request goes to, how to do that?
Thank you.
You could use Spring WebFlux Functional Endpoints
a lightweight functional programming model in which functions are
used to route and handle requests
that will give you more flexibility and control comparing to controllers.
#Bean
RouterFunction<ServerResponse> xyzRoute() {
return route(POST("/v1/xyz"), req -> handler(req));
}
Mono<ServerResponse> handler(ServerRequest serverRequest) {
return evaluateCondition()
.flatMap(condition -> {
if (Boolean.TRUE.equals(condition)) {
retrun handler1(serverRequest);
} else {
retrun handler2(serverRequest);
}
});
}
Mono<ServerResponse> handler1(ServerRequest serverRequest) {
...
}
Mono<ServerResponse> handler2(ServerRequest serverRequest) {
...
}
I am writing a custom REACTIVE Health Indicator (i.e. by implementing ReactiveHealthIndicator) to check the connectivity to another app. However to check this I require some request parameter in the request URL of /health endpoint.(e.g. URL that i want is "/health?countryCode=IN") is there a way to achieve this? Please note that as it is reactive, autowiring HttpServletRequest won't work.
#Component
public class CustomServicesHealthIndicator implements ReactiveHealthIndicator {
#Override
public Mono<Health> health() {
//#TODO : This will be called like localhost:8080/acuator/health?param=value.
// Need to read value of 'param' here and take some actions accordingly
return doHealthCheck()
.onErrorResume(ex -> Mono.just(new Health.Builder().down(ex).build()));
}
private Mono<Health> doHealthCheck(){
return Mono.just(new Health.Builder().up().build());
}
}
Documentation : https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-features.html#reactive-health-indicators
We are using token authentication in our WebAPI application. Every call (other then method which obtains key) uses same pattern.
Authorization: our-token v01544b7dce-95c1-4406-ad4d-b29202d0776c
We implemented authentication using Attribute and IActionFilter
Controllers look like so:
[RoutePrefix("api/tms/auth")]
public class AuthController : BaseController
{
public ISecurityService SecurityService { get; set; }
[TokenAuth]
[Route("logout")]
[HttpPost]
public HttpResponseMessage Logout()
{
try
{
this.SecurityService.InvalidateAccessToken(this.StaticContextWrapperService.AccountId, token, HttpContext.Current.Request.UserHostAddress);
// Return OK status
return new HttpResponseMessage(HttpStatusCode.OK);
}
catch (LoginException le)
{
return this.LogoutFailureResponse(le.Message);
}
}
private HttpResponseMessage LogoutFailureResponse(string message)
{
return new HttpResponseMessage(HttpStatusCode.BadRequest)
{
Content = new StringContent(message, Encoding.UTF8, "text/plain")
};
}
}
Swagger config has following:
c.ApiKey("our-token", "header", "Our Token Authentication");
Swagger UI showing "Authorize" button and I can paste token into field on popup.
However, no headers passed in any tests. And no methods have "lock" icon on them.
EDIT:
I also tried:
c.ApiKey("our-token", "header", "Our Token Authentication", typeof(TokenAuthAttribute));
Where attribute is just attribute:
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public class TokenAuthAttribute : Attribute
{
}
Then we use IActionFilter to check if attribute applied to method and thats where we check for permission. This is done to use service via DI.
EDIT2:
I made change to how Attribute declared:
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public class TokenAuthAttribute : AuthorizeAttribute
{
}
After than Swagger UI started to show all methods as secured, so it does analyze that it's in fact AuthorizeAttribute, not just Attribute
After that it started to put header like so:
our-token: ZGV2OnYwMTA2YjZmYjdhLWRlNTUtNDZlNC1hN2Q4LTYxMjgwNTg2M2FiZQ==
Where it should be:
Authorization: our-token GV2OnYwMTA2YjZmYjdhLWRlNTUtNDZlNC1hN2Q4LTYxMjgwNTg2M2FiZQ==
If I'm not mistaken you should have:
c.ApiKey("our-token", "header", "Our Token Authentication", typeof(TokenAuthAttribute));
With that in place, all the actions tagged with TokenAuth should show a lock icon
You can see it in action in one of mine:
https://turoapi.azurewebsites.net/swagger/ui/index
And the code behind that is here:
https://github.com/heldersepu/TuroApi/blob/master/TuroApi/App_Start/SwaggerConfig.cs#L67
For below URL's I receive a 404 error, this is fine since the URL's do not exist. Is it possible to create these servlets while the server is running before the error page is returned ?
http://127.0.0.1:8888/test1
http://127.0.0.1:8888/test1/test2
I'm thinking perhaps to create a generic controller that intercepts all urls if the current servlet does not exist, then create it ?
Assuming that by Spring you mean Spring MVC, you could do something like this:
#Controller
public class YourController {
#RequestMapping("/mappingA")
public void methodA() {
// (...)
}
#RequestMapping("/mappingB")
public void methodB() {
// (...)
}
// Catches all non-matched requests.
#RequestMapping("/*")
public void fake404(HttpServletRequest request) {
var uri = request.getRequestURI();
// (...)
}
}
In a WebAPI service, we are using a Formatter to read a content parameter on a request. We need access to the URL in order to transform the content parameter correctly. HttpRequestMessage isn't available, and we can't use HttpContext.Current.Request because HttpContext.Current is null. Accessing the HttpRequestMessage on a Read was requested at http://aspnetwebstack.codeplex.com/workitem/82, but this issue was closed because HttpContent is available on a Read. However, I don't know how to get the URL from HttpContent, or even if it's possible.
There is a method called GetPerRequestFormatterInstance on the formatter which you can override to create a new instance of the formatter with the stateful information about the request in it. By the way, this method GetPerRequestFormatterInstance is only called during the request's deserialization stage. Example below:
public class TextPlainFormatter : BufferedMediaTypeFormatter
{
public TextPlainFormatter()
{
this.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/plain"));
}
public HttpRequestMessage CurrentRequest
{
get;
private set;
}
public override MediaTypeFormatter GetPerRequestFormatterInstance(Type type, HttpRequestMessage request, MediaTypeHeaderValue mediaType)
{
TextPlainFormatter frmtr = new TextPlainFormatter();
frmtr.CurrentRequest = request;
//Copy from the original formatter instance to the new instance
frmtr.MediaTypeMappings.Clear();
foreach (MediaTypeMapping mediaTypeMapping in this.MediaTypeMappings)
{
frmtr.MediaTypeMappings.Add(mediaTypeMapping);
}
frmtr.RequiredMemberSelector = this.RequiredMemberSelector;
frmtr.SupportedEncodings.Clear();
foreach (Encoding supportedEncoding in this.SupportedEncodings)
{
frmtr.SupportedEncodings.Add(supportedEncoding);
}
frmtr.SupportedMediaTypes.Clear();
foreach (MediaTypeHeaderValue supportedMediaType in this.SupportedMediaTypes)
{
frmtr.SupportedMediaTypes.Add(supportedMediaType);
}
return frmtr;
}