Host-independent URL from code - javascript

I need my app to send email with a link back to the app in it. How do I form the link, no matter which host/port/etc it is running on? In one place, I do this:
var urlToSend = req.protocol + '://' + req.get('host') + "some/path";
But I don't have simple access to the req object in my new case. That string manipulation seems goofy and error-prone to begin with. Jumping through hoops to get the request would make it even worse, I think.
Is there something in nodejs like url helper functions in rails?

Looking at those URL helper functions, I don't see any that give you the hostname. You're right in that capturing it from req.hostname is a bit sloppy.
I'd recommend conditionally setting an environment variable as long as your setup isn't too complex. After that, use the url module that McMath mentioned.
if (process.env.NODE_ENV === "production") {
process.env.HOSTNAME = "site.com"
} else if (process.env.NODE_ENV === "development") {
process.env.HOSTNAME = "localhost"
}

Take a look at the url module in Node. url.format() should serve your purposes. For example, you can do something like this:
'use strict';
const url = require('url');
// Just for example:
const PROTOCOL = 'https';
const HOST = 'some.host.com';
const PATH = 'some/path';
// ...
var urlToSend = url.format({
protocol: PROTOCOL,
host: HOST,
pathname: PATH
});
// urlToSend = 'https://some.host.com/some/path'
You shouldn't need access to the req object just to construct a link. The relevant protocol, host, path, etc., should all be available somewhere in your app, unless there is something I'm missing about your question.
Update
I agree with #MitchLillie that you should make your app configurable using environment variables. I just thought I would expand on a suggestion I make in the comments below. It is a common pattern in Node to have a file (or perhaps several files) specifically for configuration, such as setting your host, port, etc. The file would normally contain default values that you could optionally override with environment variables, like so:
// config.js
module.exports = {
protocol: process.env.PROTOCOL || 'https',
host: process.env.HOST || 'some.host.com',
// ...
};
And then you can just require('./config.js') wherever you need access to these settings. It helps to maintain consistency as your app grows, and makes it easy to change your settings if necessary.

Related

How to set url in index.html in swagger-UI

I am using Swagger-UI for jax-rs jersey.
So there is this index.html. There you have to enter the url for the swagger.json .
So this is a big problem.
We are deploying our application to a lot different environments.
And the respective swagger.json will always be on the same environment.
We have Jenkins build jobs and we cannot edit index.html for every environment.
window.onload = function() {
// Begin Swagger UI call region
const ui = SwaggerUIBundle({
url: "**https://petstore.swagger.io/v2/swagger.json**",
Property url I always have to set.
What should I do?
P.S.
In Springfox Swagger-UI there is no physical swagger.json
But in jax-rs I have this dist folder and there is always a physical json
as far as I understand. Where should I put this so all different
clients can access it.
You can use vanilla JS for that:
var currentUrl = window.location.origin;
var apiBasePath = currentUrl + '/v2';
window.ui = SwaggerUIBundle({
url: apiBasePath + "/swagger.json",
...
})

Is it possible to get full url (including origin) from route in VueJS?

In this example:
const resolved = this.$router.resolve({
name: 'about'
})
console.log(resolved.route.path)
Is it possible to get route with origin included? Like, if the url is site.com/about, the code would give /about, so I'll need to append origin myself: window.location.origin + resolved.route.path.
I've been using this (tested with vue-router v4, browser only):
const route = router.resolve({ /* your route here */ });
const absoluteURL = new URL(route.href, window.location.origin).href;
Edit: Used location.origin instead of location.href since resolve().href already includes base.
No, not from the router.
Even the router's base property is relative to the app root:
The base URL of the app. For example, if the entire single page application is served under /app/, then base should use the value "/app/".
$route.fullPath also begins at the app root. The docs describe it as:
The full resolved URL including query and hash.

Extracting table value from an URL with Node JS

I am quite new to Node JS and express but I am trying to build a website which serves static files. After some research I've found out that NodeJS with Express can be quite useful for this.
So far I managed to serve some static html files which are located on my server, but now I want to do something else:
I have an URL to an html page, and in that html page, there is a table with some information.
I want to extract specific a couple of values from it, and 1) save it as JSON in a file, 2) write those values in a html page. I've tried to play with jQuery, but so far I've been unsuccessful.
This is what I have so far:
1.node app running on port 8081, which I will further access it from anywhere with NGINX reverse proxy (I already have nginx setup and it works)
2.I can get the URL and serve it as HTML when I use the proper URI.
3.I see that the table doesn't have an ID, but only the "details" class associated with it. Also, I am only interested in getting these rows:
<div class='group'>
<table class='details'>
<tr>
<th>Status:</th>
<td>
With editors
</td>
</tr>
From what I've seen so far, jQuery would work fine if the table has an ID.
This is my code in app.js
var express = require('express');
var app = express();
var request = require('request');
const path = require('path');
var content;
app.use('/', function(req, res, next) {
var status = 'It works';
console.log('This is very %s', status);
//console.log(content);
next();
});
request(
{
uri:
'https://authors.aps.org/Submissions/status?utf8=%E2%9C%93&accode=CH10674&author=Poenaru&commit=Submit'
},
function(error, response, body) {
content = body;
}
);
app.get('/', function(req, res) {
console.log('Got a GET request for the homepage');
res.sendFile(path.join(__dirname, '/', 'index.html'));
});
app.get('/url', function(req, res) {
console.log('You requested table data!!!');
TO DO: SHOW ONLY THE THE VALUES OF THAT TABLE INSTEAD OF THE WHOLE HTML PAGE
res.send(content);
});
var server = app.listen(8081, function() {
var host = server.address().address;
var port = server.address().port;
console.log('Node-App listening at http://%s:%s', host, port);
});
Basically, the HTML content of that URL is saved into content variable, and now I would like to save only the table from it, and also output only the saved part to the new html page.
Any ideas?
Thank you in advance :)
Ok, So I've come across this package called cheerio which basically allows one to use jQuery on the server. Having the html code from that specific URL, I could search in that table the elements that I need. Cheerio is quite straight-forward and with this code I got the results I needed:
var cheerio = require('cheerio');
request(
'https://authors.aps.org/Submissions/status?utf8=%E2%9C%93&accode=CH10674&author=Poenaru&commit=Submit',
(error, res, html) => {
if (!error && res.statusCode === 200) {
const $ = cheerio.load(html);
const details = $('.details');
const articleInfo = details.find('th').eq(0);
const articleStatus = details
.find('th')
.next()
.eq(0);
//console.log(details.html());
console.log(articleInfo.html());
console.log(articleStatus.html());
}
}
);
Thank you #O.Jones and #avcS for guiding me to jsdon and html-node-parser. I will definitely play with those in the near future :)
Cheers!
Your task is called "scraping." You want to scrape a particular chunk of data from some web page you did not create and then return it as part of your own web page.
You have noticed a problem with scraping: often the page you're scraping does not cleanly identify the data you want with a distinctive id. So you must use some guesswork to find it. #AvcS pointed out a server-side npm library called jsdom you can use for this purpose.
Notice this: Even though browsers and nodejs both use Javascript, they are still very different environments. Browser Javascript has lots of built-in APIs to access web pages' Document Object Models (DOMs). But nodejs doesn't have those APIs. If you try to load jQuery into node.js, it won't work, because it depends on browser DOM APIs. The jsdom package gives you some of those DOM APIs.
Once you have fetched that web page to scrape, code like this may help you get what you need.
const jsdom = require("jsdom");
const { JSDOM } = jsdom;
...
const page = new JSDOM(page_in_text_string).window;
Then you can use a subset of the DOM APIs to find the elements you want in your page. In your example, you are looking for elements with the selector div.class table.group. You're looking for the div.class element.
You can do this sort of thing to find what you need:
const desiredTbl = page.document.querySelector("div.class table.group");
const desiredDiv = desiredTbl ? desiredTbl.parentNode : null;
const result = desiredDiv ? desiredDiv.textContent : null;
Finally do this:
page.close();
Your question says you want certain rows from your document. HTML document don't have rows, they have elements. If you want to extract just parts of elements (part of the table rather than the whole thing) you'll need to use some text-string code. Just sayin'
Also, I have not debugged any of this. That is left to you.
There's a smaller and faster library to do similar things called node-html-parser. If performance is important you may want that one instead.

Unexpected URL generated while using window.location.hostname

I am trying to append URL, but it the generated URL is not as expected. Below is the code that I've tested and its outcome.
Since I'm using a local server to test my system, the desired request URL is http://127.0.0.1:8000/api/posts. I will be deploying this system to a remote server in the near future so I cannot use the request URL as it is now. Base on the code below, what I am trying to do is to get the current hostname and append it with the route URL but it produces weird URL. How to solve this?
Component
created() {
var test = window.location.hostname + '/api/posts';
this.axios.get(test).then(response => {
this.posts = response.data.data;
});
Route Api (api.php)
Route::get('/posts', 'PostController#index');
Just use an absolute URL in your axios requests if you don't want to have to configure a base URL:
this.$axios.get('/apiposts')
Where the prefixed / is the important part.
You probably do not need to set baseURL. Have you tried to define baseURL? For example:
axios.get(`${process.env.HOST}:${PORT}/api/categories`)
Add this code in your: /src/main.js
const baseURL = 'http://localhost:8080';
if (typeof baseURL !== 'undefined') {
Vue.axios.defaults.baseURL = baseURL;
}
See the solution here Set baseURL from .env in VueAxios
I think in your app baseURL is set to http://127.0.0.1:8000 (default) and you append the host to this url in this line var test = window.location.hostname + '/api/posts';. Try it without this.

st. skip 'path' part of URI if it's already provided in request

my st instance configured with
var mount = st({
path: './app/',
url: '/', // defaults to path option
index: 'index.html',
cache: {
fd: none,
content: none
}
});
so when I send request to res/img/1.jpg it goes to ./app/res/img/1.jpg That's pretty much clear. But if have some requests to app/res/img/1.jpg then it redirect this requests to ./app/app/res/img/1.jpg and of course find nothing, because I have different file structure.
Is it possible to configure st or maybe add some custom code to skip path adding if it's already exist in URI? Or maybe it possible some way to add specific path which handles different, like some exclusions?
I don't know if it possible to do that with st directly, but you simply could add code to rewrite url if it met for some cases.
ad code like
var exceptions = {
'wrong_path':'right_path'
}
function rewriteUrl(req){
if(exceptions[req.url]){
req.url = exceptions[req.url];
}
}
and then call that function before st method calling
http.createServer(function (req, res) {
rewriteUrl(req);
mount(req, res);
}).listen(1234);

Categories