NodeJS send http request with absoluteURI - node.js

I'm working with a weird HTTP server that only accepts HTTP request which looks like:
GET http://10.0.0.1/test
Host: 10.0.0.1
Cache-Control: no cache
Connection: Keep-Alive
Node the "http://" at the path
When I'm sending HTTP request (using the code at the bottom) the request looks like:
GET /test
Host: 10.0.0.1
Cache-Control: no cache
Connection: Keep-Alive
Code example:
var request = require('request');
var options = {
'method': 'GET',
'uri': 'http://10.0.0.1/test',
'headers': {
'Host': '10.0.0,1',
'Cache-Control': 'no cache',
'Connection': 'Keep-Alive'
}
};
request(options, function (error, response) {
if (error) throw new Error(error);
console.log(response.body);
});
Any idea how I can send the request like the server expects using standard libaries?

Related

The node.js client request header is being displayed as host: 127.0.0.1 , connection : 'Close'

I have to print from the server the request header sent by the client.
var qs = require('querystring');
var http = require('http');
const { request } = require('https');
// create server with anonymous callback function
http.createServer(function (request, response) {
response.writeHead(200, { 'Content-Type': 'text/plain' });
var options = {
method: 'HEAD',
host: '127.0.0.1',
port: '40012'
};
//here is where the server should display the clients request header
var clientHeader = request.headers;
console.log(request.headers);
}).listen(40012, '127.0.0.1');
console.log('Server running http://127.0.0.1:40012');
console.log('Process ID:', process.pid);
The server is printing only: { host: '127.0.0.1:40012', connection: 'close' }
What am I doing wrong?
I've tried executing your code locally. and I got the following response. on hitting the URL http://127.0.0.1:40012
Server running http://127.0.0.1:40012
Process ID: 52240
{
host: 'localhost:40012',
connection: 'keep-alive',
'sec-ch-ua': '" Not A;Brand";v="99", "Chromium";v="99", "Google Chrome";v="99"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"Linux"',
'upgrade-insecure-requests': '1',
'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36',
accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
'sec-fetch-site': 'none',
'sec-fetch-mode': 'navigate',
'sec-fetch-user': '?1',
'sec-fetch-dest': 'document',
'accept-encoding': 'gzip, deflate, br',
'accept-language': 'en-US,en;q=0.9,hi;q=0.8,gu;q=0.7,ar;q=0.6,en-GB;q=0.5',
cookie: 'token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjp7Il9pZCI6IjYxNzEzYzVmOWYzYjAzZWIyMmQ0NmYzNSIsImVtYWlsIjoicmFqZW5kcmEyMDc5MUBnbWFpbC5jb20ifSwiaWF0IjoxNjM0ODQzMzI4fQ.CgQWS5dImbFCNnvBpbtAuWyjpScRSTYxvZvhDmHQ0Lw'
}
However, the code is incomplete so the request from the browser will be stuck. the complete code can be as follows. We need to give a response to the client.
var http = require('http');
// create server with anonymous callback function
http.createServer(function (request, response) {
response.writeHead(200, { 'Content-Type': 'text/plain' });
//here is where the server should display the clients request header
console.log(request.headers);
// This is response body.
response.write('This is response');
// This will mark the end of the response.
response.end();
}).listen(40012, '127.0.0.1');
console.log('Server running http://127.0.0.1:40012');
console.log('Process ID:', process.pid);

Forwarding FormData() request from NodeJS to another service

I am trying to forward my request from my NodeJS Proxy server to another server. The request I am trying to forward contains FormData()
I created FormData as per MDN docs
const payload = new FormData();
payload.append('addresses', file); // <---- UPLOADED FILE
payload.append('reason', 'reason');
payload.append('type', 'type');
This is how I am essentially sending the request to my NodeJS server
fetch("localhost:3000/v1/addresses", {
method: 'PUT',
body: payload
});
NodeJS Server at localhost:3000
const multer = require('multer');
const upload = multer();
app.put('/v1/addresses', upload.single('addresses'), (req, res) => {
let options = {
host: 'localhost',
method: 'PUT',
port: 8000,
path: req.originalUrl,
headers: req.headers,
formData: {
reason: req.body.reason,
type: req.body.type,
}
};
console.log("reason", req.body.reason) // "reason"
console.log("type", req.body.type) // "type"
console.log("addresses", req.file) // FILE OBJECT
const request = http.request(options, response => {
res.writeHead(response.statusCode, response.headers);
response.pipe(res);
});
request.end();
})
The code above, I'm not sure how to send over the actual file to the other service. Also, I am NOT seeing the reason and and type that I've passed over to the service.
What's also strange is that I see this in the incoming request in my NON- PROXY server
PUT /v1/addresses HTTP/1.1
Host: localhost:3000
Connection: keep-alive
Content-Length: 932
Sec-Ch-Ua: "Google Chrome";v="89", "Chromium";v="89", ";Not A Brand";v="99"
Sec-Ch-Ua-Mobile: ?0
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryt2p0AWOqJCnz95hg
Accept: */*
Origin: http://localhost:3000
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: http://localhost:3000/blocklist
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
[object Object]
So after lots of searching and experimenting, this post actually provided me with the answer
Here is the code from the post.
const express = require("express");
const app = express();
const bodyParser = require('body-parser');
var multer = require('multer')();
const FormData = require('form-data');
const axios = require('axios');
const fs = require('fs');
app.use(bodyParser.json());
app.post('/fileUpload' , multer.single('fileFieldName'), (req , res) => {
const fileRecievedFromClient = req.file; //File Object sent in 'fileFieldName' field in multipart/form-data
console.log(req.file)
let form = new FormData();
form.append('fileFieldName', fileRecievedFromClient.buffer, fileRecievedFromClient.originalname);
axios.post('http://server2url/fileUploadToServer2', form, {
headers: {
'Content-Type': `multipart/form-data; boundary=${form._boundary}`
}
}).then((responseFromServer2) => {
res.send("SUCCESS")
}).catch((err) => {
res.send("ERROR")
})
})
const server = app.listen(3000, function () {
console.log('Server listening on port 3000');
});

nodejs cannot perform http post with autorization header

this is the request i want to perform:
POST /v1/oauth2/token HTTP/1.1
Host: api.sandbox.paypal.com
Accept: application/json
Accept-Language: en_US
Authorization: Basic cGF5cGFsaWQ6c2VjcmV0
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials
I tried it in nodejs using this code:
paypalSignIn = function(){
var username = process.env.PAYPALID;
var password = process.env.PAYPALSECRET;
var auth = 'Basic ' + Buffer.from(username + ':' + password).toString('base64');
// new Buffer() is deprecated from v6
// auth is: 'Basic VGVzdDoxMjM='
var post_data = querystring.stringify({
'grant_type' : 'client_credentials',
});
var header = {'Accept': 'application/json', 'Authorization': auth, 'Accept-Language': 'en_US'};
const options = {
hostname: 'api.sandbox.paypal.com',
port: 443,
path: '/v1/oauth2/token',
method: 'POST',
headers: header,
}
var post_req = http.request(options, function(res) {
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log('Response: ' + chunk);
});
});
post_req.write(post_data);
post_req.end();
}
Unfortunately i'm getting the following error:
Error: socket hang up
Try using the https module (it's not enough to set port 443, you have to use the HTTPS protocol to connect to an HTTPS endpoint).
I also noticed you didn't set the Content-Type header. It depends on the API, but that may cause problems for you too.
Finally, I'd consider using a library that wraps http/https like node-fetch, bent, or axios for this rather than the standard library directly. It can handle things like writing to the socket, setting the Content-Length header, etc.

Cannot view authorization header

I'm using node.js default HTTP module and have an HTTP webserver.
I use request.headers to get all headers, but when I try to do request.headers.authorization it returns undefined, but there IS authorization as you can see here.
I tried to do JSON.parse(request.headers).authorization, still undefined, and crashes the process. How can I get the authorization header content?
Maybe you could use the method request.getHeader(name)
I looked in https://nodejs.org/api/http.html#http_request_getheader_name
Edit 1:
index.js
const http = require('http');
const server = http.createServer((request, response) => {
console.log(request.headers);
console.log(request.headers.authorization);
console.log('----');
const headers = {
'Content-Type': 'text/plain',
};
let statusCode = 404;
response.writeHead(200, headers);
response.end('Hi');
});
server.listen(8080, () => {
console.log(`Server listening on port :8080 🚀`);
});
Executing in terminal one:
node index.js
Terminal two:
curl localhost:8080 -H 'authorization: hello'
The output in terminal one is:
{ host: 'localhost:8080',
'user-agent': 'curl/7.68.0',
accept: '*/*',
authorization: 'hello' }
hello
----

CORS - OPTIONS ... 404 (not found)

Hi I'm having a problem with CORS.
GENERAL STRUCTURE:
Angular 4 sends data of a Form to my api.
Function saveForm() is executed when I send information about form contact.
app.component.ts
saveForm() {
let headers = new Headers();
headers.append('Content-Type', 'application/json');
let requestOptions = new RequestOptions({ headers: headers });
// Encode JSON as string to exchange data to web server.
this.data = JSON.stringify(this.myContact);
this.http.post('https://pablocordovaupdated.herokuapp.com/api', this.data, requestOptions).subscribe(res => {
let result = res.json();
if(result['result'] == 'success') {
this.successMessage = true;
}
}
);
}
Here is the root of problem, because I'm using POST and Content-Type->application/json to send my data and by definition It gives me a problem with CORS - preflighted request, here more definition: Link about preflighted request
This meaning that before angular 4 sends the data to the server, this asks to server if it is available to receive my data with the verb OPTION, if the response of server is OK then angular 4 sends the data of form.
PROBLEM:
In console I always get this error message:
OPTIONS https://pablocordovaupdated.herokuapp.com/api 404 (Not Found)
XMLHttpRequest cannot load
https://pablocordovaupdated.herokuapp.com/api. Response to preflight
request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'https://pablocordova.herokuapp.com' is therefore not
allowed access. The response had HTTP status code 404.
XHR failed loading: POST
"https://pablocordovaupdated.herokuapp.com/api".
ERROR Response {_body: ProgressEvent, status: 0, ok: false,
statusText: "", headers: Headers…}
WHAT I TRIED:
so far, I understand that problem is because https://pablocordovaupdated.herokuapp.com/api doesn't return answer for verb OPTIONS
then I tried to resolve this of 2 ways:
Using cors package CORS package
I configured according documentation.
var express = require('express');
var cors = require('cors');
...
var app = express();
...
app.options('/api', cors());
app.post('/api', cors(), function(req, res, next) {
// Proccess to send this data via email
// and also save in data base(only for learning)
});
But I get in console the same error.
Configuring headers manually by Discussion StackOverFlow or Discussion Github
That code is inserted inside every route that I want to write the headers, in my case:
app.post('/api', function(req, res, next) {
if (req.method === 'OPTIONS') {
console.log('!OPTIONS');
var headers = {};
// IE8 does not allow domains to be specified, just the *
// headers["Access-Control-Allow-Origin"] = req.headers.origin;
headers["Access-Control-Allow-Origin"] = "*";
headers["Access-Control-Allow-Methods"] = "POST, GET, PUT, DELETE, OPTIONS";
headers["Access-Control-Allow-Credentials"] = false;
headers["Access-Control-Max-Age"] = '86400'; // 24 hours
headers["Access-Control-Allow-Headers"] = "X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept";
res.writeHead(200, headers);
res.end();
} else {
// Process to send this data via email
// and also save in data base(only for learning)
}
});
Here the problem is that never execute console.log('!OPTIONS');
Here also I tried simply:
app.post('/api', function(req, res, next) {
console.log('!I AM YOUR FATHER');
...
});
but never is printed.
Note: I tried to see this message with heroku logs because the whole page is in Heroku.
But also doing this I get the same error.
MORE INFORMATION:
When the .../api is called, I have this headers
**GENERAL**:
Request URL:https://pablocordovaupdated.herokuapp.com/api
Request Method:OPTIONS
Status Code:404 Not Found
Remote Address:23.21.185.158:443
Referrer Policy:no-referrer-when-downgrade
**RESPONSE HEADERS**:
HTTP/1.1 404 Not Found
Connection: keep-alive
Server: Cowboy
Date: Wed, 10 May 2017 04:14:45 GMT
Content-Length: 494
Content-Type: text/html; charset=utf-8
Cache-Control: no-cache, no-store
**REQUEST HEADERS**:
OPTIONS /api HTTP/1.1
Host: pablocordovaupdated.herokuapp.com
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Access-Control-Request-Method: POST
Origin: https://pablocordova.herokuapp.com
User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.96 Safari/537.36
Access-Control-Request-Headers: content-type
Accept: */*
Referer: https://pablocordova.herokuapp.com/
Accept-Encoding: gzip, deflate, sdch, br
Accept-Language: es-ES,es;q=0.8
QUESTION:
That is my true problem or I am understanding bad? and/or
What can I do to solve that problem? and/or
Any advices?
Thanks.
The problem seems to be: https://pablocordovaupdated.herokuapp.com/api always returns 404:
$ curl -i https://pablocordovaupdated.herokuapp.com/api
HTTP/1.1 404 Not Found
That is, the server isn’t doing anything special/different for the OPTIONS request — instead all requests are just hitting that 404.
app.post('/api', function(req, res, next) {
console.log('!I AM YOUR FATHER');
...
});
I’m not super clear on how Express handles this case, but it may be that must configure it to send some kind of response for that route — not just a console.log on the server side.
When I look at the content of https://pablocordovaupdated.herokuapp.com/api what I see is just a generic Heroku 404 page — so it’s not being served from your app but instead falling back to being served by Heroku. For example, the contents of that 404 page have this:
<iframe src="//www.herokucdn.com/error-pages/no-such-app.html"></iframe>
That is, it appears to be that request for that URL are never getting handled as expected by your app code at all under any circumstances. So it seems like that’s what you need to fix first.

Resources