React routing with spring mvc - spring-mvc

I'm making an webapp using react and spring mvc. I've got 2 questions while making it.
How do you request mapping?
I want to map all the uris but resources and apis into index.jsp, react SPA entry.
resouce uris start with /res
api uris start with /api
How do you response url that react recognize. I mean If you put /examples/1 on your browser, then the web server retutns index.jsp with uri /examples/1 so that react redirects itself to /examples/1.
Thanks.

I've made a controller like this,
#RequestMapping("/api/**")
public ApiResult api(HttpServletRequest request, HttpServletResponse response){
return apiProxy.proxy(request, reponse);
}
#RequestMapping(value="/**", method=HTTPMethod.GET)
public String index(){
return "index"
}
and setup spring config like this.
<mvc:resource mapping="/res/**" location="/res/" order="-1"/>
order -1 is very important.
It makes spring to check first the request url matches with resource mapping.

Related

Asp .Net Identity Server - Allow wildcard redirect URLs for Vercel

I'm using Duende IdentityServer with RestApi as back-end and I'm using Vercel to test the front-end but can't login to the IdentityServer with vercel because of the redirectUrl of vercel is not allowed.
I did see some information about it in other questions but it is from few years back and not really covering the issue, I wonder if someone manage to implement a solution for that in identityserver and can share the information and code.
I know wildcard redirect URLs are bad because of security reasons but this is just for develop environment and not going to be part of release.
I'm just starting to get into Asp .Net and any help will be appreciate!
One option is to use the AddAppAuthRedirectUriValidator extension method which:
Adds a an “AppAuth” (OAuth 2.0 for Native Apps) compliant redirect URI
validator (does strict validation but also allows http://127.0.0.1
with random port).
builder.Services.AddIdentityServer()
.AddApiAuthorization<ApplicationUser, ApplicationDbContext>()
.AddAppAuthRedirectUriValidator();
If this is still not enough, you can register your own redirect URI validator using the AddRedirectUriValidator extension method:
builder.Services.AddIdentityServer()
.AddApiAuthorization<ApplicationUser, ApplicationDbContext>()
.AddRedirectUriValidator<MyRedirectUriValidator>();
MyRedirectUriValidator.cs:
// allows arbitrary redirect URIs - only for demo purposes. NEVER USE IN PRODUCTION
public class MyRedirectUriValidator : IRedirectUriValidator
{
public Task<bool> IsPostLogoutRedirectUriValidAsync(string requestedUri, Duende.IdentityServer.Models.Client client)
{
return Task.FromResult(true);
}
public Task<bool> IsRedirectUriValidAsync(string requestedUri, Duende.IdentityServer.Models.Client client)
{
return Task.FromResult(true);
}
}
Duende IdentityServer DI Extension Methods

Redirect file upload to another server with Spring Web

Redirect file upload to another server with Spring Web
I have a server application based on Spring MVC (not Spring Boot). It is developed in Kotlin. This application should process a very specific upload request. All it should do is forward this request to another server. So the RestController works like a proxy. Is it possible to create this functionality with Spring resources alone or is a third party library required?
The RestController may look like this. It provides an endpoint for a file upload (multipart form data). The addtional parameter resourceId is used together with the injected baseApiUrl to create the url to the external server which is the final recipient of the upload.
#RestController
class UploadForwarderRestController(
#Value("#{environmentProps['externalService.base-api-url']}") baseApiUrl: String
) {
#PostMapping(
value = ["/myresource/{resourceId}"],
consumes = [MediaType.MULTIPART_FORM_DATA_VALUE],
produces = [MediaType.ALL_VALUE]
)
fun forwardUpload(
#RequestParam myResource: MultipartFile,
#PathVariable resourceId: Int
): ResponseEntity<Any?> {
// ...
}
}
Is it possible to do this in one go or does the RestController have to cache the file before it can be forwarded to the target server?

ServletUriComponentsBuilder.fromRequest return http scheme instead of https

I have a web application composed by frontend code that invokes the same api implemented by two backend modules. This api returns a url in a JSON object. The backend modules are both written with spring mvc but in different versions.
The url-building is the same and it is something like this:
#GetMapping(path = "/app1/menu", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public JsonObject getMenu(HttpServletRequest req) throws IOException {
JsonObject menu = new JsonObject();
menu.addProperty("href", ServletUriComponentsBuilder.fromRequest(req)
.replacePath(req.getContextPath())
.path("/index.html")
.toUriString());
return menu;
}
As you can see this code simply adds a constant to the incoming request and returns it.
The first app uses spring mvc 4 (4.3.5.RELEASE precisely).
The second module uses the 5.1.4.RELEASE version.
When all these apps are deployed on a load balanced server (2 tomcat instance with a load balancer upfront) and https the problem shows up.
Say that the request url is, for app1, something like this:
https://example.com/context/app1/menu
The app1 returns correctly
https://example.com/context/index.html
For the app2 the request issued by the frontend is
https://example.com/context/app2/menu
And the answer is
http://example.com/context/another_index.html
So it looses the https scheme
It seems that the ServletUriComponentsBuilder.fromRequest has changed behaviour?
I have taken a (quick I admit) look at the commits in the git repo but haven't
found anything ....

How to configure emberjs routes in SpringMVC?

We have an Ember frontend and Spring Boot backend.
When Ember runs standalone on port 4200 and the Spring Boot backend on 8080, then everything works. But this scenario is somewhat unusual for production environments, not only because of CORS problem. The URL of the backend must be known already on build time (!) of the Ember application, because it's integrated within the compiled ember app. This is not possible for many projects. Therefore, we want to integrate the frontend Ember App in the Spring Boot backend, which is usual for e.g. SPA with AngularJS.
The Ember app (from /dist) is thus copied to src/main/resource/static. After adjusting the rootURL and API.host with the Ember app that works very well.
The problem arises now, when a manual reload for an URL is made in the browser. Such a URL is now an Ember route. The http-request arrives at the Spring Boot backend which don't knows the route and we got a 404 error.
How should SpringMVC (as part of the Spring Boot backend) answers the httpRequest for such a route, so that the Ember app continue their work and handle the request ?
HTML Page request (by browser)
http://host/springBootAppContext/index.html => src/main/resource/static/index.html (ember app)
REST API request (by Ember App)
http://host/springBootAppContext/users => RESTController mapped for /users
Ember Routing (by Ember App)
http://host/springBootAppContext/user-list => ???
You can't provide a normal Spring MVC #Controller class because the ModelView response is interpretet as user-list.html or similar which doesn't exist
after tests with different solutions I came up with a really simple one.
Provide a normal, non-REST controller with request mappings for every route defined by the ember app. Every such request have to be answered with the view name of the ember app start page (index.html in most cases). The browser loads that html page and starts the containing ember app. The ember app detects the route (because the route was part of the http request) and work according all specified route configurations (template, model, controller).
No 404 NotFound any more.
#Controller
public class EmberRouteController {
public static final String INDEX = "index.html";
#RequestMapping(value = "/ember-route-1", method = RequestMethod.GET)
public String emberRoute1() {
return INDEX;
}
#RequestMapping(value = "/ember-route-2", method = RequestMethod.GET)
public String emberRoute2() {
return INDEX;
}
}
The previous answer helped me a lot. But I was still thinking of better solution than creating backend APIs for each route. And I feel the better solution would be to put '#' in before ember route then ember routes serves the request rather than going to the backend server.
Router.reopen({
location: 'hash'
});
Ex: http://localhost:8008/#/first
Here first is my route. And I have put # in the URL, now reload of the page is working.
Hope this will help.

Where to hook up authentication in Grizzly?

I'm using a Grizzly HttpServer which has two HttpHandler instances registered:
under /api/* there is an Jersey REST - style application offering the API of the product, and
under /* there is an StaticHttpHandler which serves static HTML / JavaScript content (which, among other things, talks to the API under /api/
For authentication I'm currently securing only the API using a Jersey ContainerRequestFilter implementing HTTP Basic Auth, which looks quite similar to what is presented in another SO question.
But as requirements changed, now I'd like to require authentication for all requests hitting the server. So I'd like to move the authentication one level up, from Jersey to Grizzly. Unfortunately, I'm completely lost figuring out where I can hook up a "request filter" (or whatever it is called) in Grizzly. Can someone point me to the relevant API to accomplish this?
The easiest solution would leverage the Grizzly embedded Servlet support.
This of course would mean you'd need to do a little work to migrate your current HttpHandler logic over to Servlets - but that really shouldn't be too difficult as the HttpHandler API is very similar.
I'll give some high level points on doing this.
HttpServer server = HttpServlet.createSimpleServer(<docroot>, <host>, <port>);
// use "" for <context path> if you want the context path to be /
WebappContext ctx = new WebappContext(<logical name>, <context path>);
// do some Jersey initialization here
// Register the Servlets that were converted from HttpHandlers
ServletRegistration s1 = ctx.addServlet(<servlet name>, <Servlet instance or class name>);
s1.addMapping(<url pattern for s1>);
// Repeat for other Servlets ...
// Now for the authentication Filter ...
FilterRegistration reg = ctx.addFilter(<filter name>, <filter instance or class name>);
// Apply this filter to all requests
reg.addMapping(null, "/*");
// do any other additional initialization work ...
// "Deploy" ctx to the server.
ctx.deploy(server);
// start the server and test ...
NOTE: The dynamic registration of Servlets and Filters is based off the Servlet 3.0 API, so if you want information on how to deal with Servlet listeners, init parameters, etc., I would recommend reviewing the Servlet 3.0 javadocs.
NOTE2: The Grizzly Servlet implementation is not 100% compatible with the Servlet specification. It doesn't support standard Servlet annotations, or deployment of traditional Servlet web application archive deployment.
Lastly, there are examples of using the embedded Servlet API here
The "hookup" part can be done using a HttpServerProbe (tested with Grizzly 2.3.5):
srv.getServerConfiguration().getMonitoringConfig().getWebServerConfig()
.addProbes(new HttpServerProbe.Adapter() {
#Override
public void onRequestReceiveEvent(HttpServerFilter filter,
Connection connection, Request request) {
...
}
#Override
public void onRequestCompleteEvent(HttpServerFilter filter,
Connection connection, Response response) {
}
});
For the "linking" to the ContainerRequestFilter you might want to have a look at my question:
UnsupportedOperationException getUserPrincipal

Resources