Sending request to webserver using axios - javascript

I want to send an array of strings over localhost 3000 with route start then send back a response with status 200 and eventually a map attached to response.body Currently i have this
Client code:
const axios = require('axios');
let listOfNames = ['mikey'];
axios.post(''http://localhost:3000/start'', {
data: { names: listOfNames }
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
Server code:
const express = require('express');
const app = express()
const port = 3000
var listOfNames = [];
app.post('/start', async (req, res) => {
listOfNames = req.params.listOfNames;
res.status(200).send("Names added");
});
app.listen(port, () => {
console.log('request recieved');
});
I get this error presemably from how the request is being sent, any help?
TypeError [ERR_INVALID_URL]: Invalid URL
at new NodeError (node:internal/errors:393:5)
at URL.onParseError (node:internal/url:565:9)
at new URL (node:internal/url:645:5)
at dispatchHttpRequest (C:\Users\cmb\rectangleHealth\node_modules\axios\dist\node\axios.cjs:23
94:20)
at new Promise (<anonymous>)
at http (C:\Users\cmb\rectangleHealth\node_modules\axios\dist\node\axios.cjs:2330:10)
at Axios.dispatchRequest (C:\Users\cmb\rectangleHealth\node_modules\axios\dist\node\axios.cjs:
3260:10)
at Axios.request (C:\Users\cmb\rectangleHealth\node_modules\axios\dist\node\axios.cjs:3610:33)
at Axios.httpMethod [as post] (C:\Users\cmb\rectangleHealth\node_modules\axios\dist\node\axios
.cjs:3649:19)
at Function.wrap [as post] (C:\Users\cmb\rectangleHealth\node_modules\axios\dist\node\axios.cj
s:27:15) {
input: '/start',
code: 'ERR_INVALID_URL'
}
Edit: New error ECONNRESET error emerging from applied fixes
AxiosError: read ECONNRESET
at AxiosError.from (C:\Users\cmb\rectangleHealth\node_modules\axios\dist\node\axios.cjs:789:14
)
at RedirectableRequest.handleRequestError (C:\Users\cmb\rectangleHealth\node_modules\axios\dis
t\node\axios.cjs:2744:25)
at RedirectableRequest.emit (node:events:513:28)
at eventHandlers.<computed> (C:\Users\cmb\rectangleHealth\node_modules\follow-redirects\index.
js:14:24)
at ClientRequest.emit (node:events:513:28)
at Socket.socketErrorListener (node:_http_client:494:9)
at Socket.emit (node:events:513:28)
at emitErrorNT (node:internal/streams/destroy:151:8)
at emitErrorCloseNT (node:internal/streams/destroy:116:3)
at process.processTicksAndRejections (node:internal/process/task_queues:82:21) {
syscall: 'read',
code: 'ECONNRESET',
errno: -4077,
The console also outputs a 2 json objects called request and config that cannot fit into this post.

I noticed 2 things errors in your code:
First, check your url is correct, instead of
''http://localhost:3000/start'' (you have multiple single quotes wrapping the url)
try,
"http://localhost:3000/start" or 'http://localhost:3000/start' (wrap it in proper double quotes or single quotes)
Second, You are passing the data in your api call as request body and not as request parameters, but you are trying to access it in the parameters of your api.
You should try accessing the request's body on the server side instead of parameters,
app.post('/start', async (req, res) => {
listOfNames = req.body.listOfNames;
res.status(200).send("Names added");
});
Else you might probably face issue while accessing the data in api as well.

Related

How to pass form-data in Loopback code in Mocha Unit Testing NodeJs

I am trying Unit Testing Using Loopback Mocha. I have a POST API /admin/url/createShortUrl which requires actualUrl as a formdata. Also some headers. But headers seems working fine.
I tried multiple answers from stackoverflow but none worked. I am trying to set Content-type as application/json as well as multipart/form-data. But none of it is working.
require('dotenv').config();
import {Client, expect} from '#loopback/testlab';
import {BrickAdminPanelApplication} from '../../application';
import upload from 'multer';
import {setupApplication} from './test-helper';
admin-panel.datasource';
const token =
'eyJ0eXAiOiJKV1QiLCJhbGci';
describe('ShortenedUrlController', () => {
let app: BrickAdminPanelApplication;
let client: Client;
before('setupApplication', async () => {
({app, client} = await setupApplication());
});
after(async () => {
await app.stop();
});
it('invokes POST /admin/url/createShortUrl', async () => {
await client
.post('/admin/url/createShortUrl')
.set({Authorization: `Bearer ${token}`})
.set('emailId', 'myemail#gmail.com')
.set('Content-Type', 'multipart/form-data') //Not working
.set('Content-Type', 'application/json') //Not working
.field('Content-Type', 'multipart/form-data') //Not working
.field(
'actualUrl',
'https%3A%2F%2Fadminss.papers.com%2Fddqwderss1ssdadsdassatsddqposissdcsuy',
)
.expect(400);
});
});
ERROR
1) ShortenedUrlController
invokes POST /admin/url/createShortUrl:
Error: expected 400 "Bad Request", got 415 "Unsupported Media Type"
at Context.<anonymous> (src\__tests__\acceptance\url-shortener.acceptance.ts:92:8)
at processImmediate (node:internal/timers:466:21)
at process.callbackTrampoline (node:internal/async_hooks:130:17)
at Test._assertStatus (node_modules\supertest\lib\test.js:304:12)
at C:\project test\MT-PampersBrick-Admin-API\node_modules\supertest\lib\test.js:80:15
at Test._assertFunction (node_modules\supertest\lib\test.js:338:11)
at Test.assert (node_modules\supertest\lib\test.js:209:21)
at localAssert (node_modules\supertest\lib\test.js:167:12)
at fn (node_modules\supertest\lib\test.js:164:5)
at Test.callback (node_modules\superagent\src\node\index.js:902:3)
at fn (node_modules\superagent\src\node\index.js:1130:18)
at IncomingMessage.<anonymous> (node_modules\superagent\src\node\parsers\json.js:19:7)
at IncomingMessage.emit (node:events:539:35)
at endReadableNT (node:internal/streams/readable:1345:12)
at processTicksAndRejections (node:internal/process/task_queues:83:21)

GCS catch error if file not found in bucket while streaming download

I am trying to fetch images from google cloud storage bucket from browser and serving the files using API in express. Following code breaks when the Image path is invalid. The try catch doesn't catch the file not found error. Am I missing something here? This code works if an image file exists.
From the Express side, I am using wildcard route (i.e. /*) as the API can accept any image path coming in and try to serve it.
const express = require('express')
const {Storage} = require('#google-cloud/storage');
let server = express()
const storage = new Storage();
const bucketName = '<some-bucket-name>'
server.get('/*', async (req, res) => {
const widthString = req.query.width
const heightString = req.query.height
const format = req.query.format
const fileName = req.path.substring(1);
console.log("url: ", req.path)
let width, height
if (widthString) {
width = parseInt(widthString)
}
if (heightString) {
height = parseInt(heightString)
}
res.type(`image/${format || 'png'}`)
try{
await storage.bucket(bucketName).file(fileName).createReadStream().pipe(res)
} catch (err) {
console.error(err);
}
})
Error:
url: /media/artist/banner_image/16118/screenshot_2019_12_16_at_10.35.24_am.png
events.js:377
throw er; // Unhandled 'error' event
^
ApiError: No such object: assets/media/artist/banner_image/16118/screenshot_2019_12_16_at_10.35.24_am.png
at new ApiError (/home/ubuntu/imageoptimizer/node_modules/#google-cloud/common/build/src/util.js:73:15)
at Util.parseHttpRespMessage (/home/ubuntu/imageoptimizer/node_modules/#google-cloud/common/build/src/util.js:175:41)
at Util.handleResp (/home/ubuntu/imageoptimizer/node_modules/#google-cloud/common/build/src/util.js:149:76)
at Duplexify.<anonymous> (/home/ubuntu/imageoptimizer/node_modules/#google-cloud/storage/build/src/file.js:888:31)
at Duplexify.emit (events.js:400:28)
at PassThrough.emit (events.js:400:28)
at onResponse (/home/ubuntu/imageoptimizer/node_modules/retry-request/index.js:222:19)
at PassThrough.<anonymous> (/home/ubuntu/imageoptimizer/node_modules/retry-request/index.js:163:11)
at PassThrough.emit (events.js:412:35)
at /home/ubuntu/imageoptimizer/node_modules/teeny-request/build/src/index.js:191:27
Emitted 'error' event on PassThrough instance at:
at emitErrorNT (internal/streams/destroy.js:106:8)
at emitErrorCloseNT (internal/streams/destroy.js:74:3)
at processTicksAndRejections (internal/process/task_queues.js:82:21) {
code: 404,
Posting my previous comment as an answer for visibility
You have to handle this exception by yourself. GCP won't throw the error directly. It only returns 404 as an output, and you have to handle it manually rather than expecting try{} catch () {} to catch this exception. Or you can request it as a new feature in issue tracker, however I am not sure how long it will take for the Google to implement this feature.

Self signed certificate error when fetching API locally

I have a simple .NET Core WebAPI with no authentication. I added Cors with default policy. I have no problem connecting and fetching data from my React website or Postman (everything runs locally on my machine). Now I'm trying to fetch data from that API in super simple node application and I'm getting this error:
file:///Users/aw/Projects/TestNodeApp/node_modules/node-fetch/src/index.js:94
reject(new FetchError(`request to ${request.url} failed, reason: ${error.message}`, 'system', error));
^
FetchError: request to https://localhost:5001/api/teams failed, reason: self signed certificate
at ClientRequest.<anonymous> (file:///Users/aw/Projects/TestNodeApp/node_modules/node-fetch/src/index.js:94:11)
at ClientRequest.emit (node:events:394:28)
at TLSSocket.socketErrorListener (node:_http_client:447:9)
at TLSSocket.emit (node:events:394:28)
at emitErrorNT (node:internal/streams/destroy:157:8)
at emitErrorCloseNT (node:internal/streams/destroy:122:3)
at processTicksAndRejections (node:internal/process/task_queues:83:21) {
type: 'system',
errno: 'DEPTH_ZERO_SELF_SIGNED_CERT',
code: 'DEPTH_ZERO_SELF_SIGNED_CERT',
erroredSysCall: undefined
}
This is my whole node application:
import fetch from 'node-fetch';
async function fetchTeams() {
const response = await fetch('https://localhost:5001/api/teams', { method: 'GET' });
const data = await response.json();
return data;
}
(async () => {
console.log('Process started');
const teams = await fetchTeams();
console.log(teams);
})().finally(() => {
console.log('Process finished');
});
What does it mean? What Am I missing?
Btw. It works fine, when I'm fetching Github API, like this:
async function fetchGithub() {
const response = await fetch('https://api.github.com/users/Microsoft');
const data = await response.json();
return data;
}
So I assume, something is missing in the API. Something that my React website doesn't need, that node app needs.
Thanks for help!
You can use this command to set the NODE_TLS_REJECT_UNAUTHORIZED environment variable:
export NODE_TLS_REJECT_UNAUTHORIZED=0
Try trusting the self signed certificate with dotnet dev-certs
dotnet dev-certs https --trust
For more details please visit this documentation page.

Https request Post from an Angular App to ExpressJS Node.js Server results in request write() end() is not a function and socket hang up Error

I am trying to invoke an Authorization Token API to get an access token.
The trigger is from an angular application via a button click.
The angular service code is below:
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { User } from './../auth/user';
import { AuthResponse } from './../auth/auth-response';
import { tap } from 'rxjs/operators';
import { Observable, BehaviorSubject } from 'rxjs';
#Injectable({
providedIn: 'root'
})
export class AuthService {
AUTH_SERVER = "http://localhost:3000";
authSubject = new BehaviorSubject(false);
constructor(private httpClient: HttpClient) { }
register(user: User): Observable<AuthResponse> {
return this.httpClient.post<AuthResponse>(`${this.AUTH_SERVER}/register`, user).pipe(
tap((res: AuthResponse ) => {
if (res.token) {
console.log("ACCESS_TOKEN : "+ res.token.access_token);
localStorage.set("ACCESS_TOKEN", res.token.access_token);
localStorage.set("EXPIRES_IN", res.token.token_type);
localStorage.set("ACCESS_TOKEN", res.token.expires_in);
localStorage.set("EXPIRES_IN", res.token.refresh_token);
this.authSubject.next(true);
}
})
);
}
}
And the NodeJS Backend service code is below:
const express = require('express')
const https = require('https')
const app = express()
const router = express.Router();
const cors = require('cors');
const bodyParser = require("body-parser")
const api_helper = require('./util/api_helper')
const port = 3000
app.use(cors());
router.use(bodyParser.urlencoded({ extended: false }));
router.use(bodyParser.json());
router.get('/', (req, res) => {
res.status(200).send('Welcome to Make REST API Calls to Authorisation Server In Express!');
});
router.post('/register', (req, res) => {
console.log('nodejs user name = '+req.body.username);
console.log('nodejs password = '+req.body.password);
var client_id = 'xxxx';
var client_secret = 'yyyyyy';
var auth_header = 'Basic ' + Buffer.from(client_id + ':' + client_secret).toString('base64');
const data = "grant_type=password&username=ddddd&password=eeeeee&client_id=fff&client_secret=Joe75";
const options = {
hostname: 'linux-2222',
port: 8543,
path: '/xxxx/oauth2/token',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-formurlencoded',
'Content-Length': data.length
}
};
const requestVar = https.request(options, (res) => {
console.log(`statusCode: ${res.statusCode}`)
res.on('data', (chunk) => {
console.log(`BODY: ${chunk}`);
});
res.on('end', () => {
console.log('No more data in response.');
});
});
requestVar.write(data);
requestVar.end();
req.on('error', (error) => {
console.log('error is ' + error);
});
});
app.use(router);
app.listen(port, () => console.log(`Node server listening on port ${port}!`))
The error I am getting is below:
Entering the server endpoint
nodejs user name = xxx
nodejs password = yyyy
(node:6285) Warning: Setting the NODE_TLS_REJECT_UNAUTHORIZED environment variable to '0' makes TLS connections and HTTPS requests insecure by disabling certificate verification.
**TypeError: req.write is not a function**
at /Users/admin/Development/mod/integrator/src/app/app.js:78:7
at invokeCallback (/Users/admin/Development/mod/integrator/node_modules/raw-body/index.js:224:16)
events.js:288
throw er; // Unhandled 'error' event
^
Error: socket hang up
at connResetException (internal/errors.js:604:14)
at TLSSocket.socketOnEnd (_http_client.js:460:23)
at TLSSocket.emit (events.js:323:22)
at endReadableNT (_stream_readable.js:1204:12)
at processTicksAndRejections (internal/process/task_queues.js:84:21)
Emitted 'error' event on ClientRequest instance at:
at TLSSocket.socketOnEnd (_http_client.js:460:9)
at TLSSocket.emit (events.js:323:22)
at endReadableNT (_stream_readable.js:1204:12)
at processTicksAndRejections (internal/process/task_queues.js:84:21) {
code: 'ECONNRESET'
}
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! integrator#0.0.1 start: `NODE_TLS_REJECT_UNAUTHORIZED='0' node ./src/app/contractor_lifecycle_app.js`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the integrator#0.0.1 start script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! /Users/admin/.npm/_logs/2020-03-28T11_37_38_559Z-debug.log
The nodejs console shows errors with :
TypeError: req.write is not a function and Error: socket hang up.
FYI, I am getting the access token in postname using the relevant http request options. And I was able to use the access token to get a protected resource in postman.
But, I cannot even consume the authorization endpoint via nodejs express.
Please, I need someone to help, any ideas will do.
It appears the problem is with the https.request logic, but I dont know exactly where.
NOTE: The request parameter from the angular app is being successfuly logged in the console in the nodejs https request post function.
The req in the following line:
router.post('/register', (req, res) => {
was overriding the following:
req.write(data);
req.end();
The request write() and end() are methods of the object returned from https.request(options, (res) => {
So, I have updated the code by assigning the https.request(options, (res) => { .. to a new varibale called requestVar.
And now I am getting my acccess token from the authorization server.
I have updated original post with the fix.
Hurray.

Error: Can't set headers after they are sent. RabbitMQ interfering with NodeJS response

After a http response, I am sending a messing using RabbitMQ (creating a channel etc) and however, the server is complaining that "Error: Can't set headers after they are sent."
Here is the code:
var amqp = require('amqplib');
var when = require('when');
var rabbitmq_conn = amqp.connect('amqp://localhost' );
function push_keystroke_data(session_id, data) {
var QUEUE_NAME = 'hello';
var msg = session_id;
when(rabbitmq_conn.createChannel()).then(function(ch) {
var ok = ch.assertQueue(QUEUE_NAME, {durable: false});
ok.then(function(_qok) {
ch.sendToQueue(QUEUE_NAME, new Buffer(msg));
console.log(" [x] Sent '%s'", msg);
ch.close();
});
}).ensure(function() {
conn.close();
});
}
router.post('/', function(req, res, next) {
// current session id
var sid;
if (req.cookies.papi) {
sid = req.cookies.papi.session_id;
} else {
sid = generate_session_id();
res.cookie('papi', {session_id: sid}, {maxAge: COOKIE_MAX_AGE});
}
res.send(JSON.stringify({ user_id: get_user_id(sid)}));
var data = process_keystroke_data(req.body);
push_keystroke_data(sid, data);
});
I assuming RabbitMQ is setting the headers after the response (I have also tried sending the RabbitMQ message before the response but that also didn't solve anything).
Here is the stack trace:
POST /api 500 220.100 ms - 16
Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:335:11)
at ServerResponse.header (/Users/mikeecb/Documents/KeyNA/jsbackend/node_modules/express/lib/response.js:700:10)
at ServerResponse.send (/Users/mikeecb/Documents/KeyNA/jsbackend/node_modules/express/lib/response.js:154:12)
at fn (/Users/mikeecb/Documents/KeyNA/jsbackend/node_modules/express/lib/response.js:934:10)
at View.exports.renderFile [as engine] (/Users/mikeecb/Documents/KeyNA/jsbackend/node_modules/jade/lib/index.js:374:12)
at View.render (/Users/mikeecb/Documents/KeyNA/jsbackend/node_modules/express/lib/view.js:93:8)
at EventEmitter.app.render (/Users/mikeecb/Documents/KeyNA/jsbackend/node_modules/express/lib/application.js:566:10)
at ServerResponse.res.render (/Users/mikeecb/Documents/KeyNA/jsbackend/node_modules/express/lib/response.js:938:7)
at /Users/mikeecb/Documents/KeyNA/jsbackend/app.js:62:7
at Layer.handle_error (/Users/mikeecb/Documents/KeyNA/jsbackend/node_modules/express/lib/router/layer.js:58:5)
Any solutions or ideas would be much appreciated.
It turns out that the issue was not that RabbitMQ was setting the headers (which would be weird, why would it be doing any http stuff?) but that after responding res.send(JSON.stringify({ user_id: get_user_id(sid)}));, I tried to send another respond which obviously the issue.

Categories