How do I serve both web pages and API Routes by using same port address and different Handle pattern - api

I have simple web application with CRUD operation, I want to serve web pages and API routes using same port address and different Handle pattern. As follows,
fs := http.FileServer(http.Dir("server/webapps/play_maths"))
http.Handle("/", fs)
http.Handle("/api", call API routes)
Following is my API routes
func UserRoutes() *mux.Router {
var router = mux.NewRouter()
router = mux.NewRouter().StrictSlash(true)
router.HandleFunc("/user/create", api.CreateUser)
router.HandleFunc("/user/get/all", api.GetAllUsers)
return router
}

This is supported by the net/http package out-of-the-box. Quoting from http.ServeMux:
Patterns name fixed, rooted paths, like "/favicon.ico", or rooted subtrees, like "/images/" (note the trailing slash). Longer patterns take precedence over shorter ones, so that if there are handlers registered for both "/images/" and "/images/thumbnails/", the latter handler will be called for paths beginning "/images/thumbnails/" and the former will receive requests for any other paths in the "/images/" subtree.
So simply you can register your file handler to path /, and register an API handler to e.g. /api/ path. In this scenario any requests that start with /api/ will be directed to the API handler, and any other requests will be directed to the file handler.
Note that this of course means if there are files that are in the /api/ folder (or more specifically whose request paths start with /api/), they won't be reachable for the above mentioned reason.

I did following changers to my code and now it's running as I expected.
func main() {
//Starting the API server
router := routes.UserRoutes()
http.Handle("/api/", router)
//Starting the FileServer
fs := http.FileServer(http.Dir("server/webapps/play_maths"))
http.Handle("/", fs)
log.Println("Listening...")
log.Fatal(http.ListenAndServe(":3000", nil))
}
Then I change my routes as follows.
func UserRoutes() *mux.Router {
var router = mux.NewRouter()
router = mux.NewRouter().StrictSlash(true)
router.HandleFunc("/api/user/create", api.CreateUser)
router.HandleFunc("/api/user/get/all", api.GetAllUsers)
return router
}

Related

ASP.NET Core Endpoint - route all calls to specific route first

What do I need to change this to route all requests to /api/ShibAuth?
endpoints.MapGet("/", async context =>
{
context.Response.Redirect("/api/ShibAuth");
});
The code above obviously routes any calls to root URL and I've already tried what I though was appropriate wildcard.
What do I need to change this to route all requests to /api/ShibAuth?
Well, if I correctly understand the requirement, you would like all of your request to redirect to this /api/ShibAuth route at the begining.
Certainly, we can implement above scenario using UriBuilder class which provides the functionality to modify HttpRequest.Path. Finally, rebuild the request URI and redirect to your expected path. You can do as following
Solution:
app.MapGet("/", async context =>
{
var originalUrl = context.Request.GetDisplayUrl();
var routeToCallFirst = "api/ShibAuth";
var updatedUrl = (new UriBuilder(originalUrl) { Host = context.Request.Host.Host, Path = routeToCallFirst }).Uri;
context.Response.Redirect(updatedUrl.AbsoluteUri);
});
Output:
Note: Here, I am redirecting the all landing request to /api/ShibAuth controller from the middleware.

Check if request is made to Razor Page

How can I check within middleware code if current request is made to Razor Page not to any other resource (static file, or API)?
All my APIs are located within api folder, so if (!context.Request.Path.StartsWithSegments("/api")) {} filters out APIs, but that will not work for static content as these files and libraries are placed within number of folders what results in number of URL segments.
Could not find any relevant property in context.
First step - place the middleware after app.UseRouting(). Any request for a static file will never reach your middleware because the static files middleware will short circuit the request. Also, after this point, the routing middleware will have selected the endpoint and populated the endpoint metadata. Then you can test the endpoint metadata collection to see if it includes PageRouteMetaData, which tells you that this is a Razor page route:
app.Use((context, next) => {
var endpoint = context.GetEndpoint();
if (endpoint != null)
{
foreach(var md in endpoint.Metadata)
{
if( md is PageRouteMetadata)
{
// this is a page route
}
}
}
return next(context);
});

How to call an express.js handler from another handler

I'm building an isomorphic React application which is using express.js on the server. The client app makes a number of AJAX requests to other express handler which currently entails them making multiple HTTP requests to itself.
As an optimisation I'd like to intercept requests I know the server handles and call them directly (thus avoiding the cost of leaving the application bounds). I've got as far as accessing the apps router to know which routes it handlers however I'm struggling to find the best way to start a new request. So my question is:
How do I get express to handle an HTTP request that comes from a programatic source rather than the network?
I would suggest create a common service and require it in both the handlers. What I do is break the business logic in the service and create controllers which handles the request and call specific services in this way u can use multiple services in same controller eg.
router.js
var clientController = require('../controllers/client-controller.js');
module.exports = function(router) {
router.get('/clients', clientController.getAll);
};
client-controller.js
var clientService = require('../services/client-service.js');
function getAll(req, res) {
clientService.getAll().then(function(data) {
res.json(data);
}, function(err) {
res.json(err);
});
}
module.exports.getAll = getAll;
client-service.js
function getAll() {
// implementation
}
module.exports.getAll = getAll;
u can also use something like http://visionmedia.github.io/superagent/ to make http calls from controllers and make use of them.

Restelet routing: some resources require authentication, some don't. How to do it?

I've been workin on a RESTlet 2.1 project. I've figured out how to set up authentication for my Resources. Fact is.. not all of them need authentication! I am quite puzzled about how should I do it right.
In the following code you can see the outline of my server Application, in particular the "create Inbound Root":
#Override
public Restlet createInboundRoot(){
/* the structure so far is: a filter, followed by an authenticator,
followed by a rooter.
The filter is returned at end of the method.
*/
//Init filter:
SomeFilter someFilter = new SomeFilter();
//Init authenticator:
ChallengeAuthenticator authenticator = new ChallengeAuthenticator(
......);
//more authenticator stuff goes here....
//Init router:
Router router = new Router(getContext());
//this should be a public resource, no need for auth:
router.attach("/0.1/getResource", SomeResource.class)
//this is a private resource, needs auth:
router.attach("/0.1/getPrivateResource", PrivateResource.class);
//set up the flow: filter -> authenticator -> router
authenticator.setNext(router);
someFilter.setNext(authenticator);
return someFilter;
}
The filter must be before everything, since I need to modify some Headers for all packages. After the filter I would like to set-up a fork, where requests of my public resource are just routed to the Resource class and requests of the private resource must pass through the authenticator.
How can I accomplish this? I am new to this framework and couldn't figure out even if it looks dead simple.
Think about your routers like a chain. Yours look like this:
someFilter -> authenticator -> router -> (SomeResource.class | PrivateResource.class)
This means all requests start at someFilter, go through the authenticator, hit the router and end up at either SomeResource or PrivateResource.
You need to put the authenticator in front of PrivateResource only, move the authenticator to that bit of the chain, so it looks more like this:
someFilter -> router -> (SomeResource.class | authenticator -> PrivateResource.class)
The code might look like:
ChallengeAuthenticator authenticator = new ChallengeAuthenticator(......);
authenticator.setNext(PrivateResource.class);
router.attach("/0.1/getPrivateResource", authenticator);
Does that help?
I've figured out the full solution to this, it was about "URI templates". The one thing missing was the different way a router can match the uri, in fact, the problem needed a "Match the first part of the URI" kind of approach.
/*
* Routing structure:
*
* ---/public---->(publicR()----> Public Resources
* (Filter()---->(routerPP()--|
* ---/private--->(authenticator()---->(privateR()---> Private Resources
*
*/
where routerPP takes the decision if the URL begins with /public or /private:
Router routerPP = new Router(getContext());
routerPP.setDefaultMatchingMode(Template.MODE_STARTS_WITH);
routerPP.attach("/private", authenticator);
routerPP.attach("/public", publicR);
the one particularity is that, after an URL "passes through" a router, it looses the matched part of the URL, therefore a following router (e.g. the public one) will have this structure:
Router publicR = new Router(getContext());
publicR.attach("/somePublicResource", SomePublicResource.class);
and such configuration matches the following URL:
http://somehost.com/public/somePublicResource
if in the second router you add the "/public/" token again, you will get a "resource not found" error, and the resource would then be on: http://somehost.com/public/public/somePublicResource
So the routers match and remove from the URL.
Reference about the routing and the URI matching I've found useful are:
http://restlet-discuss.1400322.n2.nabble.com/Trying-to-route-to-two-routes-that-start-with-same-prefix-td7019794.html
http://restlet.org/learn/javadocs/snapshot/jse/api/org/restlet/routing/Router.html

HTTP Authentication in Restlet, authenticating child URL

I am using HTTP Digest authentication mechanism in the server side and client is firefox.
This is the server side code
Application application = new Vehicle();
component.getDefaultHost().attachDefault(application);
component.getDefaultHost().attach("/home",new Home());
DigestAuthenticator guard = new DigestAuthenticator(null, "TestRealm","mySecretServerKey");
Instantiates a Verifier of identifier/secret couples based on a simple Map.
MapVerifier mapVerifier = new MapVerifier();
Load a single static login/secret pair.
mapVerifier.getLocalSecrets().put("login", "secret".toCharArray());
guard.setWrappedVerifier(mapVerifier);
Guard the restlet
guard.setNext(application);
component.getDefaultHost().attachDefault(guard);
component.start();
In home class
Router router = new Router(getContext());
router.attach("/People", People.class);
router.attach("/categories/",Categories.class);
return router;
if i request http://localhost:8182/ Http authentication is working but http://localhost:8182/home/categories/ is not asking for any http authentication if first we try for /home/categories/ instead of http://localhost:8182/ it will give out the result with out any authentication mechanism. How to solve this ?
You are attaching the guard only to the default route, so the routes that are not matching any other routes. See the javadoc for attachDefault :
* Attaches a Resource class to this router as the default target to invoke
* when no route matches. It actually sets a default route that scores all
* calls to 1.0.
Your other routes are not the default routes and so they are not guarded
router.attach("/People", People.class);
router.attach("/categories/",Categories.class);
You must wire the guard between each route that you want to protect like this :
DigestAuthenticator peopleGuard = new DigestAuthenticator(null, "TestRealm","mySecretServerKey");
peopleGuard.setNext(People.class);
router.attach("/People", peopleGuard);