Customizing Zuul url endpoints for services in JHipster - jhipster

I have a group of microservices, called "client-Foo", where Foo is the name for some particular third-party client.
Using those names as-is creates some really ugly endpoint urls, so I want to translate them to a much nicer hierarchal form.
I added a custom PatternServiceRouteMapper that take the serviceId client-Foo and turns it into the url client/Foo.
This gives the url I want, but also breaks the service mapping because it also changes the registered serviceId to client/Foo; thus, when Zuul goes to route it fails because there is no client/Foo service, its id is client-Foo!
I cannot hardcode any paths because the application requires an arbitrary number of different "client-*" services.

By looking at ZuulProxyAutoConfiguration, you can see that you can replace some beans to achieve your goal and in particular you should consider providing your own implementation of RouteLocator interface or extend DiscoveryClientRouteLocator class.
Your service instances could also register in Eureka server with additional data in metadataMap that your RouteLocator could use.

I would simply add a configuration defined Zuul route :
zuul:
routes:
client-foo: /foo/**
Also I would advise against having a dash in a service-id as it can confuse the config server api (in /config/foo-profile.yml where profile is the spring profile for which you want to get the config).

Related

What is the difference (if any) between a route and an endpoint in the context of a RESTful API?

Question
I have a probably rather simple question, but I'm unable to find an answer with nice explanations:
What is the difference (if any) between a route and an endpoint in the context of a RESTful API developed within a Node.js / Express application (but these concepts may be broader?!)?
(Does it relate to URLs in some way?)
Example
For example, in this article: https://medium.com/#purposenigeria/build-a-restful-api-with-node-js-and-express-js-d7e59c7a3dfb we can read:
We imported express which we installed at the beginning of the course, app.get makes a get request to the server with the route/endpoint provided as the first parameter, the endpoint is meant to return all the todos in the database.
These concepts are used interchangeably, which makes me confused.
(please note that I'm a 100% beginner with REST API, nodejs and express but I try to do my best to learn).
Edit
The two first answers chronologically speaking make me even more confused as they are perfectly antagonistic.
3 different concepts here:
Resource: {id: 42, type: employee, company: 5}
Route: localhost:8080/employees/42
Endpoint: GET localhost:8080/employees/42
You can have different endpoints for the same route, such as DELETE localhost:8080/employees/42. So endpoints are basically actions.
Also you can access the same resource by different routes such as localhost:8080/companies/5/employees/42. So a route is a way to locate a resource.
Read more: Endpoint vs. route
Read more: Endpoint vs. resource
Route
URI path used to access the available endpoints.
example: http://www.mywebsite.com/
Endpoint
performs a specific action.
has one or more parameter(s).
returns back data.
example: GET http://www.mywebsite.com/Products
A Route is the URI, and the Endpoint is the action performed on the URI.
Routes and endpoints are associated concepts - you can't really have one without the other.
What is an endpoint?
Generally speaking, an "endpoint" is one end of a communication channel where one system interacts with another system. This term is also used similarly in networking.
For a typical web API, endpoints are URLs, and they are described in the API's documentation so programmers know how to use/consume them. For example, a particular web API may have this endpoint:
GET https://my-api.com/Library/Books
This would return a list of all books in the library.
What is a route?
A "route" is typically code that matches incoming request paths to resources. In other words, it defines the URL and what code will be executed. A route path might contain regular expressions, patterns, parameters, and involve validation. For example, consider this route path:
"{controller}/{action}/{id?}"
In ASP.NET, pattern matching is applied, so GET https://my-api.com/Library/Books/341 would call the Books public method on the Library class, passing a parameter of 341. Routing frameworks can be very flexible and versatile.
The simplest example of an endpoint is to put a file you want to be consumed (say data.json) inside the public_html folder of your web server. It can be reached by GET https://my-api.com/data.json. The routing is handled by the web server out of the box and no routing code is required.
Some good things to read next:
Express.js - Routing
Wordpress Developer Resources - Routes and Endpoints
When to use "client-side routing" or "server-side routing"?
Endpoints are basically use to perform specific task and return data and endpoints are kind of part of a route.
For example is route and this is also a route but here both of them are returning different data not he same so, we can say that the last two parameter here is kind of end point means the id and question string.
endpoints:
/56075017/difference-between-route-and-endpoint
/56040846/how-to-use-the-classweight-option-of-model-fit-in-tensorflow-js
route:
https://stackoverflow.com/questions/56075017/difference-between-route-and-endpoint
https://stackoverflow.com/questions/56040846/how-to-use-the-classweight-option-of-model-fit-in-tensorflow-js
In this example: http://example.com/my-website/comments/123:
Route:
my-website/comments/123
Endpoints: (a fancy word for a URL with an action)
GET http://example.com/my-website/comments/123. returns the comment data.
DELETE http://example.com/my-website/comments/123. deletes the comment and returns the now-deleted comment data.

Is there a way to link a specific method to a Route in ServiceStack?

The Problem
I'm aware of the basic way to create a route/endpoint in ServiceStack using methods with names like "Get", "Post", "Any", etc inside a service but in the particular case that I'm trying to work with I have an existing service (which I can make an IService via inheritance) that can not be retrofitted w/ServiceStack attributes and currently uses DTOs for the requests and responses.
This service contains many functions that I do not want to manually mask (as this is a pass-through layer) but otherwise already conform to ServiceStack's requirements. What I'm wondering is if there's a way to manually create these routes in a way that would work like I've mocked up here. My existing functions and DTOs already contain the information I would need to define the routes so if this approach is possible it would only require me to enumerate them at initialization time as opposed to generating the services layer manually.
I noticed there is an extension method on Routes.Add that takes an Expression of type Expression> but I was not able to get that working because I believe the underlying code makes assumptions about the type of Expression generated (LambdaExpression vs MemberExpression or something like that). I also may be barking up the wrong tree if that's not the intended purpose of that function but I can not find documentation anywhere on how that variant is supposed to work.
Why?
I'm not sure this is necessary but to shed some light on why I want to do this as opposed to retrofitting my existing layers: The current code is also used outside of a web service context and is consumed by other code internally. Retrofitting ServiceStack in to this layer would make every place that consumes it require ServiceStack's assemblies and be aware of the web service which is a concern I want separated from the lower code. We were previously using MVC/WCF to accomplish this goal but we want some of the features available from ServiceStack.
the current architecture looks like this:
data -> DAL -> discrete business logic -> composition -> web service
Hopefully that makes enough sense and I'm not being obtuse. If you would like any more details about what I want to do or why I'll try to update this post as soon as possible.
Thanks!
You might use the fallback route in order to provide your own routing mechanism.
Then you get the request.Path property and route using your own mapping of path:Function which can be stored in a simple dictionary.
Anyway, if you go this path I don't see much benefit in using servicestack. It seems you just need an http handler that routes requests to existing services.

Inserting parameter to a web service call in service stack

Lets say I have the Hello World web service defined, from the Service Stack examples, but instead of just calling it as /hello/{name}, I want to be able to call it as /hello/{name}/id, where I define id to be a separate parameter (by storing it in refId, within a CustomUserSession).
In other words, I want to split the authentication and the actual web service call into 2 parts, but I don't want to expose this id in the actual web service call, because this is private, only within my system. How would I go about doing this? My ideal workflow is:
client calls web service : /hello/{name}
authentication happens. As part of this authentication, I get hold of this secret id
I now call the web service as /hello/{name}/id
It's almost as if I want to call a web service from within another web service.
I apologize if this seems like a misguided question, but how can I go about achieving this workflow?
Thanks
I recommend taking a look at ServiceStack routing. Your service will only be called if it matches an existing route (or uses a pre-defined route) which means if you only had:
[Route("/hello/{name}")]
It wont match /hello/{name}/{id} and your service wont be called. To match that route you can either have an explicit route for it, e.g:
[Route("/hello/{name}/{id}")]
But this is public info which you're saying you would like to hide. The alternative is to use a wildcard route, e.g:
[Route("/hello/{name*}")]
Which matches any /hello/* route inc. /hello, /hello/foo, /hello/foo/id, /hello/foo/id/and/more/etc.
But what gets populated in your Hello.Name property would be foo/id which you'd have to detect and parse in your service.
An alternative is to supply the hidden id in a QueryString or POST'ed form parameter which you can use in ServiceStack to further populate any request DTO, e.g. using the original route:
[Route("/hello/{name}")]
Will let you call the service with /route/foo?id=secret which if your Request DTO had an id property will be populated with secret. If you didn't have (or want) to have an id property you can still access the param with:
base.Request.QueryString["id"];
base.Request.FormData["id"];
But since you want this to be hidden, you should probably avoid passing it in the url which is visible by everyone (inc. web proxies, http logs, and other middle ware). A better place to hide a param is to pass it as a custom HTTP header, e.g: X-id: secret which you can access in your service with:
base.Request.Headers["X-id"];

Routing in WCF data services

I am creating a WCF data service on top of a EF 4.1 code first data model that goes against a multi-tenant database. In order to enforce the rules of accessing the multi-tenancy I want to require a string id (that is required by all of our MVC-based REST services) be passed as part of the url route. So, for example, right now I have a service route like this:
http://mysample.net/mysamplesvc.svc/Users
That returns all users in the db w/o a filter. I want to partition this by client by requiring the client id be passed as part of the request like this:
http://mysample.net/mysamplesvc.svc/client123/Users
If it is not passed-in or is invalid I will handle it as required. However, I do not see any example like this anywhere. I think I must be searching incorrectly as this seems like a pretty common scenario.
TIA!
The sample service at http://services.odata.org/(S(readwrite))/OData/OData.svc/ does this (it creates a new instance of the data for each (S(...)) in the URL).
The service code is the last sample on this page: http://www.odata.org/ecosystem#samplecode

Using Gaelyk URL routing in a non google app engine application

I have a Groovy Web application which is NOT being deployed on Google app engine. (GAE) I have used Gaelyk before and I like the URL routing functionality described in their doc
How do I port over just the routing functionality from Gaelyk to my basic Groovy WEB application which is not being deployed on GAE?
Note 1: I also do not want to use Grails for this application.
Note 2: I dont mind including the gaelyk jar but I rather not include anything from GAE.
If you want to implement this yourself in your own non GAE framework, the best place to start would be the source...
To start with, you'll need a class that extends javax.servlet.Filter in Gaelyk, this is the RoutesFilter class
As you can see, in the init method of the Filter, this calls loadRoutes which loads your routes.groovy script via a GroovyShell.
This shell makes use of the other classes in that same package so that it ends up populating the List<Route> routes property in the filter with instance of the Route class.
The filter (when configured by web.xml) then intercepts all requests to the server checks the URI against each route in turn (by calling the forUri method for each route), and if a match is found, it redirects or forwards as required.
If no match is found the Filter calls the next filter down the chain in the web server's context.
Hope this answers your question

Resources