Send a POST XMLHttpRequest with a body to an express node server - node.js

Basic background:
I have an express node server running a really simple website. The first page of the site has two inputs (1 text, 1 number)
<input type="text" name="xml_url" id="xml_in" placeholder="Required" />
<input type="number" min="0" name="c2" id="c2_in" placeholder="Required" />
As of right now really simple, the user inputs a url and a number, my app builds something and returns a link to a file.
My node server (basically) looks like this:
app.post('/secondPage', function(req, res){
var url = req.body.xml_url
, c2 = req.body.c2;
//some stuff happens etc...
res.render('finalpage.html', {
foo: c2andsomething
url: newurl
});
My Question/Issue:
I want to be able to not use my front end. I believe the code will basically work (besides the render, I believe I will need something along the lines of
res.send(aJsonResponse); // obviously I will need to build the json
I just don't know how I can fake this post request. I'm sort of drawing a blank here. So far I've only really tried a few websites that claim they'll send a post request etc.. and tried in the browser just typing in my url with a query string, but my app doesn't accept GET..
Hopefully this wasn't too much rambling, but I would love to hear some suggestions. Will remove if this question makes no sense.
EDIT:
Okay so I always seem to jump the gun with these questions. I just tried in the console:
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("POST", "http://192.168.1.1:3000/secondPage", true);
xmlhttp.send("foobar");
And I'm getting a CORS error.. I think I'll be able to figure this out here shortly, if you have any suggestions I would still really love to hear them.
Thanks
EDIT 2:
So I'm able to send the request and such no CORS issues.. but I'm not sure how to set the body in the request.
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("POST", "http://192.168.1.1:3000/secondPage", true);
xmlhttp.send({"xml_in":"I-thought-this-was-the-body"});
but req.body is {}

Well I solved my issue using cURL, so not the best answer but here was what I used
curl -d "xml_in=http://google.com&c2=12345" http://192.168.1.1:3000/secondPage

Related

Using webRequest API to intercept script requests, edit them and send them back

As the title says, I'm trying to intercept script requests from the user's page, make a GET request to the script url from the background, add a bit of functionality and send it back to the user.
A few caveats:
I don't want to do this with every script request
I still have to guarantee that the script tags are executed in the original order
So far I came with two solutions, none of which work properly. The basic code:
chrome.webRequest.onBeforeRequest.addListener(
function handleRequest(request) {
// First I make the get request for the script myself SYNCHRONOUSLY,
// because the webRequest API cannot handle async.
const syncRequest = new XMLHttpRequest();
syncRequest.open('GET', request.url, false);
syncRequest.send(null);
const code = syncRequest.responseText;
},
{ urls: ['<all_urls>'] },
['blocking'],
);
Now once we have the code, there are two approaches that I've tried to insert it back into the page.
I send the code through a port to a content script, that will add it to the page inside a <script></script> tag. Along with the code, I also send an index to keep sure the scripts are inserted back into the page in the correct order. This works fine for my dummy website, but it breaks on bigger apps, like youtube, where it fails to load the image of most videos. Any tips on why this happens?
I return a redirect to a data url:
if (condition) return { cancel: false }
else return { redirectUrl: 'data:application/javascript; charset=utf-8,'.concat(alteredCode) };
This second options breaks the code formatting, sometimes removing the space, sometimes cutting it short. I'm not sure on the reason behind this behavior, it might have something to do with data url spec.
I'm stuck. I've researched pretty much every related answer on this website and couldn't find anything. Any help or information is greatly appreciated!
Thanks for your time!!!

Sending nested request to node.js web server

I am about to teach creating a simple web server in node.js to my students. I am doing it initially using the http module and returning a static page. The server code looks like this:
var http = require('http');
var fs = require('fs');
http.createServer(function(request, response) {
getFile(response);
}).listen(8080);
function getFile(response) {
var fileName = __dirname + "/public/index.html";
fs.readFile(fileName, function(err, contents) {
if (!err) {
response.end(contents);
} else {
response.end();
console.log("ERROR ERROR ERROR");
}
});
}
index.html looks like this:
<!DOCTYPE html>
<html>
<head>
<title>Static Page</title>
</head>
</body>
<h1>Returned static page</h1>
<p>This is the content returned from node as the default file</p>
<img src="./images/portablePhone.png" />
</body>
</html>
As I would expect, I am getting the index.html page display without the image (because I am not handling the mime-type). This is fine; what is confusing me is, when I look at the network traffic, I would expect to have the index.html returned three times (the initial request, the image request and one for favicon.ico request). This should happen, because the only thing the web server should ever return is the index.html page in the current folder. I logged the __dirname and fileName var and they came out correctly on each request and there were indeed three requests.
So my question is, what am I missing? Why am I not seeing three index.html response objects in the network monitor on Chrome? I know one of the students will ask and I'd like to have the right answer for him.
what is confusing me is, when I look at the network traffic, I would
expect to have the index.html returned three times (the initial
request, the image request and one for favicon.ico request)
When I run your app, I see exactly three network requests in the network tab in the Chrome debugger, exactly as you proposed and exactly as the HTML page and the web server are coded to do. One for the initial page request, one for the image and one for favicon.ico.
The image doesn't work because you don't actually serve an image (you are serving index.html for all requests) - but perhaps you already know that.
So my question is, what am I missing? Why am I not seeing three
index.html response objects in the network monitor on Chrome?
Here's my screenshot from the network tab of the Chrome debugger when I run your app:
The code that you actually wrote (originally, can't be sure you won't edit the question) just serves an index.html. There is nothing in there that could read any other file (like an image).
I don't think you should teach students that syntax/mechanism because it is outdated. For starters, do not teach them to indent with tabs or four spaces. Indent with 2 spaces for JavaScript. Also, it just doesn't make sense to teach ES5 at this point. They should learn ES2015 or later (ES6/ECMAScript 2016/whatever they call it). For the current version of Node out of the box (6.6 as of writing), this would be the equivalent of what you wrote:
const http = require('http');
const fs = require('fs-promise');
http.createServer( (request, response) => {
fs.readFile(`${__dirname}/public/index.html`)
.then( data => {response.end(data)} )
.catch(console.error);
}).listen(8080);
But what you seem to be trying to do is create a gallery script.
Another thing about Node is, there are more than 300,000 modules available. So it just absolutely does not make sense to start from 0 and ignore all 300,000+ modules.
Also, within about three months, 6 at the most, async/await will land in Node 7 without requiring babel. And people will argue that kids will be confused if they don't have enough time toiling with promises, but I don't think I buy that. I think you should just teach them how to set up babel and use async/await. Overall its going to make more sense and they will learn a much clearer way to do things. And then the next time you teach the class you won't need babel probably.
So this is one way I would make a simple gallery script that doesn't ignore all of the modules on npm and uses up-to-date syntax:
import {readFile} from 'fs-promise';
import listFilepaths from 'list-filepaths';
import Koa from 'koa';
const app = new Koa();
app.use(async (ctx) => {
if (ctx.request.querystring.indexOf('.jpg')>0) {
const fname = ctx.request.querystring.split('=')[1];
ctx.body = await readFile(`images/${fname}`);
} else {
let images = await listFilepaths('./images',{relative:true});
images = images.map(i=>i.replace('images/',''));
ctx.body = `${images.map(i=> `<img src = "/?i=${i}" />` )}`;
}
});
app.listen(3000);

Meteor's Iron Router: get query parameter on both Client and Server Side

there
In my application, if someone pass a parameter on the URL I want to do different things on the template.
I know I can get on server side a query string using this.params.query but how can I pass it to client OR get this value on client-side?
In my case I will send an optional redirect on the URL, and if it was passed, after the main task, my app will redirect the user to the url given. But I just know how to see redirect on server side, not on client, so this information get lost when I, for example, submit a form
Could you help me?
You can access the router params in your template with:
Router.current().params.query
Maybe in your route you can do like this:
onBeforeAction: function() {
Session.set("query", this.params.query);
this.next();
},
Then somewhere on the client you can make a helper like this:
Template.yourTemplateName.helpers({
query: function() {
return Session.get("query");
}
});
I'm not sure what to do with your redirect, but maybe it will work in the helper. So your html would be something like:
{{#if query}}{{query}}{{/if}}
And in the helper you could possibly replace "return Session.get("query")" with something like "Router.go('/wherever-you-want-to-go');". Or just write another helper to run in your html if the query is positive.

Login via POST does not yield valid session

I am currently trying to convert a smallish app from nodejs to golang (hence the two tags) but I'm running into a bit of trouble in doing so.
Essentially it is a very simple http POST login which I can't seem to realise. The background is that my university provides a calendar export function and I would like to provide this calendar as a feed that could be added to Google Cal.
Now the thing is that I have the whole thing working in node, but I would really like to be able realise it in go aswell.
The important bit of node code would be
var query = url.parse(req.url, true).query;
var data = {
u: query.user, // Username
p: query.password, // Password
};
needle.post(LOGIN_URL, data, {}, function (error, response) {
//extract cookies etc.
});
which is working like a charm but if I try to do the same in go
import "github.com/parnurzeal/gorequest"
//...
resp, body, err := gorequest.New().Post(LOGIN_URL).Send("u=user&p=pass").End()
//extract cookies etc.
I end up an invalid (timed out) session. I already tried using just net/http in go, which doesn't seem to change anything.
The result the POST request yields is a 302 redirect to an overview page (Btw: it is ASP based). Could it be that this is what's causing the problem, since gorequest then fetches that overview page without the cookies returned in resp, effectively creating a new session that isn't authorized, or am I overlooking something terribly simple?
So it seems that I found the answer myself by following your advice and using "net/http" and digging a little deeper into what the http.Client actually does. To anyone who might encounter similar problems, here is my solution:
http.Client automatically redirects if it receives a 30x response by the server see documentation. Although one can override the redirect policy, I was unable to prevent redirection entirely.
Additionally it seems as if the client has a bug (what I would call it at least), as it drops all header upon redirect see the issue or in the source where new headers are created.
While searching around in net/http I found http.DefaultTransport which is used by http.Client and does not redirect. It seems somewhat lower level and exactly what I was after. The following piece of code demonstrates how I replaced the line realised with gorequest from above:
data := url.Values{"u": {USER}, "p": {PASS}}
req, err := http.NewRequest("POST", LOGIN_URL, bytes.NewBufferString(data.Encode()))
//I needed quite some time to figure out that I needed to set the content type accordingly
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
//...
resp, err := http.DefaultTransport.RoundTrip(req)
//...
//resp.Header["Set-Cookie"] now contains the login/session cookies
Although I need to extract cookies myself and set a few header values, the solution works perfectly and I am quite happy with it. If anybody has some improvements to my solution or any other advice I am glad to hear it. And thanks to JimB and Volker :).

fixed urls on polymer

I'm working with polymer and I'm testing all in my local environment and all is working as expected, but the problem is when I'll move it into production, where the url shouldn't be the same as in my local. In node.js I can set it via the config.json file and catch it with app.get('config') or something like that, but in polymer I cant get it, and the only chance I have is to create another endpoint with all the config.json config file, but, and here is the best part, I should hardcode this url in polymer!! (so annoying). There is some way or library or component or something that I'm missing ?
Thanks in advance guys! StackOverflow and the users helped my a lot!
UPDATE
The thing is that I'm using custom elements (because I had handlebars too and there is a little problem with the {{}}) so, in the custom elements that I created I have this (for example in the core-ajax call):
<core-ajax id="login" auto="false" method="POST" contentType="application/json" url="/app/middle/login" ....></core-ajax>
as you can see the url is a little bit hardcoded, I want to use something like this (this is what I have on the node.js endpoint application):
router.post(endpoint.login, function (req, res) {
and I want to got something like that over polymer
<core-ajax id="login" auto="false" method="POST" contentType="application/json" url="{{login}}" ... ></core-ajax>
<script>
Polymer('log-form', {
login: endpoint.login,
ready: function () {
....
})
});
</script>
I'ts more clear now? I'm not so strong on english language.
Thanks Guys, for all!

Resources