Using Swagger for Express alongside normal routes - api

I'm interested in using something like swagger-node-express to build the API for the project I'm working on. However, some parts of the app are non-api based (serving HTML instead). Has anyone got any ideas as to how I would use Swagger alongside normal routes?

You'll just need to make sure that your routes don't conflict with the Swagger routes, and your other routes will processed as usual. One easy way would be to make Swagger live under a subpath. Take a look at the docs on that score:
https://github.com/wordnik/swagger-node-express
var app = express();
var subpath = express();
app.use(express.bodyParser());
app.use("/v1", subpath);
swagger.setAppHandler(subpath);
Otherwise, you could just keep an eye out to make sure that none of the other URLs you are using in your application conflict with the Swagger URLs, and you should be able to define your routes and handlers normally. E.g. you can use Swagger to serve up docs under http://localhost:8002/api-docs.json/pet but have http://localhost:8002/foo/ do something else just by adding the route in the normal way:
app.get(/foo/, function(req, res, next) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello Foo\n');
})
Using the subpath configuration is probably the cleanest approach but you could also just keep track of the routes yourself and make sure that the Swagger routes aren't conflicting with the routes in the rest of your app.

Related

NextJS API route conflict

I have been transitioning to NextJS from CRA. I'm re-implementing authentication using SSR, and I would like to use NextJS built-in API routes to set HTTPOnly cookies.
There is a weird problem where my backend base URL is https://somesite.com/api and my frontend's - https://somesite.com/. This means that NextJS built-in API routes will be in conflict with my own backend.
I have been researching online and couldn't find any way on changing routing in NextJS, and I don't want to change base URL of my backend, since there are other services depending on it.
Has anyone had the same issue? How can I resolve this issue?
Try next.js rewrite
Rewrites allow you to map an incoming request path to a different destination path. Docs
Check Live Example here: https://stackblitz.com/edit/nextjs-rewrite
If Path is /api it'll point to JSON placeholder APIs.(ex. /api/todos)
module.exports = {
async rewrites() {
return [
{
source: '/api/:slug*',
destination: 'https://jsonplaceholder.typicode.com/:slug*'
}
];
}
};

Returned data being rendered instead of page structure in Nuxt

I'm trying to return data as JSON from the express server for a route. The data returns fine but when i open the NUXT page on the browser than the JSON data gets outputted instead of the page HTML.
Note the express route is the same as the page route. I know the routes are conflicting with each other. Do i need to have the server and front-end on different ports? Is there anything wrong i'm doing here?
Thanks
To avoid conflicts such as that you should use a prefix like /api/ or /api/v1/ something like that
In nuxt.config.js you need to define your server middleware
serverMiddleware: ["~/api/index.js"]
That file is your server. At the bottom you need to export it like this:
module.exports = {
path: "/api",
handler: app
}
Note here: app is your express app if you use express.js.
This here: const app = express();
If everything worked your root of your API should be available under host:port/api/
you cant do this if the routes for backend and frontend exactly same. this is route rules that they have to be unique and its not backend or frontend issue for e.x. you can have two routes with same url in express(api), nuxt too.
if we say the application for example is post office, the route are path to a house address (controller or action) so we can have two path to get the a house but its confusion have a same path(url or route) and different houses.
simple solutions:
as you said make the api and front separate with different ports or different domains or even have a prefix for your express routes
in express handle all of them, means return view or page with data needed instead of json data

Vue direct URL is not working, only router-link click

This may be a known Vue routing thing that I am totally missing.
So I have a .vue file that uses the url /hardware.
Here is the routing
{
path: "/hardware",
name: "Hardware",
component: () =>
import(/* webpackChunkName: "hardware" */ "../views/Hardware.vue")
},
Going to /hardware directly using a link on an external site or typing it in the address bar does not work, gives me Page Not Found.
But clicking on this link in my nav bar does work.
<router-link to="/hardware">Hardware</router-link>
Am I missing something super obvious that I missed when I was learning routing? Is this because it is a single page application? Thanks in advance for any help.
Adding that I do have history mode on, wondering if this is the issue?
const router = new VueRouter({
mode: "history",
base: process.env.BASE_URL,
routes
});
Following back from comments to answer (Netlify) Vue-router works locally and not at the hosting/deployment side like Apache/Nginx/Firebase Hosting as:
1)
Pretty-URL / Hashbang dilemma in SPA.
The server needs to redirect when your Vue project enabled history mode. in apache, just some redirect rules needed to be done via .htaccess similarly, so as most of the hosting services included Netlify (you need to check the routes redirect rules at Netlify there). As server page not found, telling us that your route doesn't have actual files under that specified /route at their side.
Previous thread: Vue Router return 404 when revisit to the url
2) If your project for Multi-page-mode instead of going hashbang SPA, Your Vue Project needed to be configured little bit further: Either via SSR or pre-rendering static files before deployment
It could be that your browser is adding a trailing slash to giving you "/hardware/" which does not match your route. In the past, I had created an alias to match both routes such as "/hardware" and "/hardware/".
I faced the same issue nowadays and decided to share my thoughts with the community.
You can easily resolve the bug just by removing mode: "history" from the Router. Then it will be automatically replaced by the hash (#) in your URLs. It's going to work then even if you'll use a direct link in the browser.
However, based on the latest SEO recommendations History mode is more preferable because URLs without # are better tracked by Google.
If you would like to save History mode, you need to enable history mode on your server. I use Express middleware and the solution in my case is next:
const express = require('express');
const history = require('connect-history-api-fallback');
const app = express();
app.use(history());
app.use(express.static('src'));
app.get('/', (req, res) => {
res.sendFile('src/index.html');
});
app.listen(3000, () => console.log('server started'));

Use KeystoneJS as a blog, but only part of the webapp

I've got a NodeJS + Angular + MySQL webapp. Is there a way I could use KeystoneJS for blog only?
I am currently serving some pages as static Express pages, and some as an Angular App with UI Router's HTML5 mode enabled.
// Serves static pages generated by Express
app.use('/staticPage', staticPage);
app.use('/anotherStaticPage', anotherStaticPage);
// Serves Angular App
app.all('/*', function(req, res, next) {
res.sendFile(__dirname + '/ui/index.html');
});
/*
Need a way to also serve a blog powered by KeystonJS
It should be accessed at /blog/:postTitle
*/
If possible, I prefer to keep my existing set-up and simply add Keystone on top of it.
There are two ways you can do so.
(1) install keystone, and inside keystones index router, add your two static routers and one app router too.
(2) Add keystone to existing Express App.
However irrespective of keystoneJS. you have to remove generic handler for angularApp.
app.all('/app/*', function(req, res, next) {...});
Or else new blog related router has to be added above Angular, as you are doing so far.

How does ExpressJS determine if a requested resource is a "static" file?

I'm using JSPM to manage my client side dependencies and serving files using ExpressJS
My Directory structure is
node_modules
routes
views
app.js
public
css
images
js
main.js
jspm_packages
system.js
npm
angular2#2.0.0-beta.7.js
I have static route setup in my Express app.js as follows:
app.use(express.static(path.join(__dirname, 'public')));
As expected when I request for GET /jspm_packages/system.js
it serves the file correctly
however when I request GET /jspm_packages/npm/angular2#2.0.0-beta.7.js
It gives me a 404 - not found.
I suspect some of those special characters in the file name are messing up express from resolving the request as a "static" file and using the correct static route.
How can I test if express is marking the request as "static"?
How can I overwrite the express regex (or whatever mechanism) express is using to mark a request as "static"?
How can I write a custom middleware using my own regex and forward the request to static instead?
thanks.
When working with express, you must make sure right middleware is registered in right order.
As per your question, How does express identifies a resource as static?, Actually express does not determine if its static or not, it does not even understand request types, what express does is execute proper middleware for given request.
When express receives a request, It goes and starts executing matching middleware in sequence until it runs out of them.
So in practice, you'll always register your static middleware first (just after request parsers and all), before your dynamic routes. Like shown below ...
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var routes = require('./routes/index');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
//Register your static middleware
app.use(express.static(path.join(__dirname, 'public')));
//Other cool code
app.use('/', routes);
Now, request will first go through express.static middleware, if it does not find a matching file, it will call next internally and pass request to next middleware in chain.
Meaning, suppose you have a static file in public directory named users and you have a route named routes.get('/users' ..... Now when user requests /users, the request will first pass to express.static and if it finds users file (which it does in this case), our route that we registered using routes.get will never get called. Now if you do the same but just remove the file named users from the public folder, then express.static middleware won't be able to find a matching file and will pass request to next middleware in chain i.e. routes.get(/users' ...`
Express does not assume or identify a resource as static by matching or using regular-expressions. If express.static middleware finds it, it will serve it else it will pass on the request to the next middleware in queue.
Though I was pretty sure, I tried to reproduce your issue, and I was served with the file with all the special characters in it, just as shown in following image.
Please reconfirm following:
Your express.static middleware gets registered first.
The resource you are trying to access exists, i.e. physical path exsists. (resource url are case insensitive, i.e. /USERS and /users both will match a file /public/users if it exists.
Make sure you don't have a typo.
If this does not resolve your issue, please share your app.js file, some content if you can't share all of it.
Hope this helps! Let me know if you need further assistance ... :)