Node.js allow only supported methods - node.js

The following is the start of an API. I'm trying to write as part of my lessons, the course is strictly node.js without any frameworks.
My attempt is to reject request with 400 if the request method is not allowed.
(if method in methoArr then allow else reject)
var http = require('http');
var fs = require('fs');
const url = require('url');
var os = require('os');
var helpers = require('./helperFunctions');
var cl = console.log.bind(console);
//init server and listen
http.createServer(function(req, res) {
//define req.url as array
let qs = url.parse(req.url).pathname;
//deal with favico request
if (req.url === '/favicon.ico') {
res.writeHead(200, {
'Content-Type': 'image/x-icon'
});
res.end();
return;
}
//return if method not allowed
const methodArr = ['GET', 'POST', 'PUT', 'DELETE', 'HEAD', 'OPTIONS'];
var allowedMethod = true;
cl(typeof req.method, typeof methodArr[0]);
if (
req.url != methodArr[0] &&
req.url != methodArr[1] &&
req.url != methodArr[2] &&
req.url != methodArr[3] &&
req.url != methodArr[4] &&
req.url != methodArr[5]
) {
allowedMethod = false;
}
if (allowedMethod) {
// cl('req.url: ', qs, 'helpers: ', helpers, 'req method: ', req.method);
res.writeHead(200);
res.write('end url: ' + qs + ' method: ' + req.method);
} else {
res.writeHead(400);
res.write(req.method + ' method not allowed\n' + 'methodArr#: ' + methodArr[0]);
}
res.end();
}).listen(3000, 'localhost');
The if logic seems ok but obviously not...tried a switch but same issue.
I would appreciate if you can explain the error in my logic.

Use:
req.method
instead of
req.url
in condition.
if (
req.method != methodArr[0] &&
req.method != methodArr[1] &&
req.method != methodArr[2] &&
req.method != methodArr[3] &&
req.method != methodArr[4] &&
req.method != methodArr[5]
){
allowedMethod = false;
}
Or you can use this code :
if(methodArr.indexOf(req.method) < 0){
allowedMethod = false;
}

Related

Can we override JSON.stringify to obtain XSS

How can we bypass this function to obtain full XSS?
var xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
response = JSON.parse(xmlHttp.responseText);
AnyFunction(response);
}
else if (xmlHttp.readyState == 4 && xmlHttp.status != 200) {
console.log(xmlHttp.responseText);
}
}
xmlHttp.open('POST', url, true);
xmlHttp.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
xmlHttp.setRequestHeader('Accept', 'application/json');
data = {'searchTerm':item}
xmlHttp.send(JSON.stringify(data));
There is only one search bar for user input.

How to add headers in node.js

I have the following headers:
X-NewRelic-ID: VQACUF9bCBABU1JQAAQPU1I=
X-Device-Descriptor-Id: YWY1Zjk5OGI5N2U1ODg0Zg
User-Agent: Sahibinden-Android/4.5.2 (671; Android 5.1.1; Android Android SDK built for x86)
x-api-key: e91092ad5ea2e030c201ce9ac4373f6b565a7842
x-client-profile: Generic_v2.1
x-device-id: d4dc022224a74bc7964cb4d449cd32c2
x-timestamp: 1591117620862
x-api-hash: DF7AB8944EDB3140BCB2A3EA9BC95F70C3200DB7
adid: b165e39f-b0ee-4b22-aee5-df3675136c2c
Content-Type: application/json; charset=utf-8
X-J3PopQvX-e: a;grA22x5m7f3tr-0iQLVuq4BLsOW3uMVgYrreUpRM5M9sSufn0I0K5QO-LrGIm1gY8IHM_GtH_7uQ-cRTU-eV9762ivhZAOpU0I2ZC_dii-H-LDjjBUj8dI1uMmlx8sJjURVN1NWhJuf7iYYkopysE4rI5Ku0OAq-vv8po6yl7vF6KA4c1JEoyeJHX0WImy3c4SV30gzj4fLe1HfYlsA1Qa3ea7pl6kE4fXnYZ0q9DbWcxT_xUBj2Hx7GPYqqdOy8LK2eVQtj_qIyBqlUMu_B1WBteBo8JpEDsCN6hVZVVOmCvzBFVrJgh3rXd-bz3J6-TAgFOgIlbKEob6SrxPFvmrjrjFz2CESgBYUe2YBkwzOMYiNfRLfYKRF9bifV53JcX25D6ycfE5wp72kRvUDsF049QUgUyEvAOIdZcOTbETQtoAOIYtvClrsZQ8lI8VuKpHaqm3z0Cz59jNvXDYSIyVGQ43BbFHYJmvuVDK5hms8YQe1AU4z-kWFEZbR1GI2SD3e1ivl5a8YQNj3YLId6HeHy1BZZ4vrMfKhRmW6RFz3E8--TDu3r9J_RyYOh7_UhJ6-KW1FQ4mnoAD-1ObhBgw7VvefrijzY6iQKbnVhR2GVs0eAMv8RvON81vgIE7eZvqv4TFbNfpFzbNDYE4JboRsrroyElH9kbRkh6xc8Y_dlXZnZqHZH8Z55f1rBAQjeci9YzxGUJ4ssJE2vlniRkUSf1IZEwpxDdeUmKjk95EmdNIuC3NapbQbeRumyoe7XBCN3GOJ860o1wfeVE_u6aPpwtWAU7Huc2wY4-0M8V-WraljaUYt3iH2qVV9K-GryALZujOmjl6lLZTFBEFqijc8=;oh90F-L4vdHrRPBFFSIfspu1OBIaoliYHzKnk2hKNKM=
X-J3PopQvX-a: 0JMyqk3jVhB_ktkVhvJjiwUXW1jwIGUwnf4AuOufJI0WLr3Urn4m1ANxyELGawEfHAh3vvz7CcPSjuByQZVxMm-jqYz7WjSseSmlZGLnkSqTaTTYN7Rfz7aZTf2fSHc-F5zaQdRGr3t_KDw17Wu1CTjo8QGWUizaHYjkkclkI2q9R7McZmd_K2dpbBGOFwuVeuH4BoTabg7m9PxQ5PoqFykgD2dp=1a8_-iWK85xHc7N0iC7Kr0CmVECcipNabR42f=D15vshVt0cxZaZZd9hFHoY_b9RrDR5AjRvUTznXmJalncdoR0Uf9oP8DEv=uwgpWYp2O1szeXLHhrH9x9uutcDvyvbikmfl4G3qMa1b9TFvkWQCU7xEKN0qE5MTF2JOkJP0K-tRspZTm1dV7hFISNrU-nNJnDr0NI7l8-97eot5jkcTL=I=_7NDicD=8LlPbyWHeWBts3RJBQndMnW9p=J2Kth5rDIrHzfxsodpT0PsEHYY--EGX7-ijux_Xy4BTzYfYIc1g5teDskpD11nxM1Z=ioeOo0Ig-ocuf9TlHQPZcGru8koECDU8AKu_eptN_B50=Molip5MRHnD994ZKDjzv3N2I85rGzEZIjAT33_VSKNcqdsPSkDzUNwYolSc272M3=mAMtA2j3vWPoTuBdxkNZ3BIlBiE2k5sjiAG8upeDiVhAOzQB8BeO2LmP4VHH88Ng5brkoHeX3ncLD4WkIw0R-9TAou3zNmsClfJ_0dszt24ISM-H0GNDwuKKFm92JswKvWQOrrRGAYZODRJCzQAZQgjn=oxnjxiznUegsD84foGvwAxZyZZq8yMGNuEUk0pePeQjxWmZznzAAolQer1JvM0iHGjRJwwfXnzTF71H8GElk-sPFYDOzje11ozUnOwgom-o5FYemTpj8aR4uHffTrQa1KwXK_KMkeuJY0Q2mXNXJo49CSbO=lqWL1fNxi5OTZsYU7q2jXCSStaNR1DuTymMBJO3IFBeNFZDysgaSFooy_4H8Oi4G-eXNkuTE3sT-m-ZRleF8aVbTuhWo_ZgWuQDHAgELj2wCeGHnmh1_AeewO4wM55Le-YSC2hGHtg2qXoruUCvlQ9XJ=pcS7PLEMfEGbpbxvOaPnHAxiMc1Ahq54ZIzo-tuxDBlrrBO9FMq0a__z_CJxD0hSgWBaF2nnrrKS4ijOOhP8s1T7nPEdEDQcbVO9Q_wNd8CVzU5yH-28cCf-ojGBemEziprBB=5uzby0OJsmUTkwNXJkiF=LEalaVMS=XMnJpPWIAhfBT7OGGB4OUMk=onoMa2GJnL4Wv4SsshAiEamEV7QKp53TIkQEXXpRXa3wvq0sjiXEH-0CGivZDiS2KK-ZgcB0d-_GMD4jifXUkEaw9xmMyNkAQ51HxxgRaqO1Io_2xVF=cz3xUIFN5dS044xhn2V2neeqHd31QL_xBAMvQd9En5rPmyHpy4tJGgYXqzOfznN87b_4xab=My0BkP8JC-=CduTE5yTzbZXpb3uAlhiVv=UvE1tCBoFGJgcqV_AJt_b80Re-2Tw0Jc-ELyVoNvFrVm4-eRFDNGYlRo0V_IRYaY3ImGsG4lyCjYRaTEFF1pI5=8e539paXrGCSQJlZ5qxcAh_454XM-frw_D=s_TiZLRYeFLdcvy1jgEbkKGEcj7DbuFxNu9_YEuto2PhPTnttYRB0XW3u-wYIfq0sEdkLVes3aEUgLg7UhVjJxKESVXZvoW2jRXgbNM0p0QnDtvC9lBz-z1U9=7UkFPLXAqG_DabIY920oEnlHpHXgDL9ifX5anNuNSvr25-BxXYRgxRnG9hah4eXAkc2PcBbqif5HA0nNxXvAzZ5j7ib=h-jqI8I84aDjehZTNxjIH=Z5gsYkTWVYO5U=cvyJ4Qe8gCJYzfDirhfR-I2lg7A5mvGJb15_tAjXLOnwI1874pJvhOUqfuD8eJpITuynP9LsqiRpEU1nw7X1s_Ray9SHU3EcGkr935P33m5CBvrNzASXSr=N7mzu-WxVjevBK9MrUNHNRfoXJfunTwGwPCYZEluL9YpTLDSZtrd470yVyZK-PHFo_TV8y=ETtA-IDysdrWrE9R-5DEQpkKpGJKGieNDHptrNMsVODRm2y_RGEzI_j-qmC8mQir2GDqTZKRWqmUzVkgCsIGviKYK5_h9JSERGlvrzkWIESKdX_skM-s1n0Q=Vm4bCmFz1hSBy3k2Dx0f8myZdLWR2E0InNHTjw5rmWELfr_=ax4l5EYJirE7sO3Wm9-eimauhNYen5KNC0PeGhJ7BLCu0eamN_PXge=r_G_HlF3xXhPA8FfkxCjV3v4fWCbtGBVIQGES0jQR0sGPmxHuZsQQ9BZuGhh9ykSYce-OmeOCu7xojRXh7PJx1AVwmhrm1jE48CTYSUfegx7p-CyeWKRkGOZ_gafCibxwnJ9mslopc0WviVvbbwBKrNuZrZlWXQrnzi8ml=oq35l4xWs0Nb7VZOYezEiUgoayg7pFm8eLV02GiU7lrpQMqF_pl04dXo3QAEwDW_YgIrLCtBoVM92dckSfScDL12nZREI3Yd-V3dkN23vFr2cFXbBKoHK2uVDTqUyzMxDgqHkXxPu3rzp9g0FSA95TgKke0ikBsX7KrdNBc9cQNgj2AouCXwIzzAExo2pa2wqJk7zXna3ObWHbgk1dpiJ=dk_Gbr3LOJ-CeTWGANr=u1Cnyo-weSvvLGMlQTJjWOedNDCtduC193Bfeqn2brGiKSUV3rx09ywipxjJVjGW=eJ_k0Cex7bIq_RNZJHso1qzQ-R=IR59XtaSyM9BLwKNJ4tOiCpMltCJyWOd0yJnYcgZSUCiLBINMh-e7F_Si-e_1c3VH5UqyENO8YvR59-IYl4qUQs5NpIEZc5Hl0lImENjL_7WsBB7jue4Ty0JPxXrYo3ME_P0Xc0UIEJKN3CQCzKl9a5ZmmMTrHyJHNNW0FSrMsAgUXRtDH_MuExGdqcEjgr-8hhoS2kAV_JER1FupukcsGi0JLegpLEYF9GLDnUoDCDrPRP5tQb21gQUpEdvozNmXdVNRCukPDJeRSSYr4iCM5=-3UzYPSDwkb=_7Ea=WvgXvKtIeKbYcF5ZPk8OU-rq_ysU2Slfaf7fgHHR4Aif2cx_ZTekL=0W5LQL3AZv2QBh-VjjNri
X-J3PopQvX-b: -1o1lvb
X-J3PopQvX-c: AEC_kwhyAQAA125LdUCpBmDn_gaT36bu5R1v7tLmaWD2Y_AhYfLAeVsrDVYa
X-J3PopQvX-d: o_2
X-J3PopQvX-f: AyT1lAhyAQAA645HTYkhB4gLDM5zokBx1RSq1NMZ34yfPEFY650x2JWUiytPAWf_BDWcuH01wH8AAEB3AAAAAA==
X-J3PopQvX-z: p
Host: api.sahibinden.com
Connection: Keep-Alive
Accept-Encoding: gzip
With each request I want to be able to regenerate following headers:
X-J3PopQvX-a
X-J3PopQvX-b
X-J3PopQvX-c
X-J3PopQvX-d
X-J3PopQvX-f
X-J3PopQvX-z
I know of XMLHttpRequest but Im not sure how to use it in this case. I am new to node.js so a bit clueless
Edit:
I am able to send my headers using this : try {
let res = await httpClient.get(url, {
headers: headers,
params: query,
});
But I want to change j3pop headers everytime I send them. Need to change them manually. Is there any way for that?
Edit1:
This code here generates new headers:
function() {
'use strict';
console.log("inside");
var afterReadyCbCalled = false;
var originalHeaders = ["X-Origin-DC", "gytp","Cache-Control", "max-age=0","X-Forwarded-For", "103.255.4.53","X-Client-SrcPort", "45244","Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8","Accept-Language", "en-US,en;q=0.5","X-Forwarded-Proto", "https","X-TLS-Version", "771","Upgrade-Insecure-Requests", "1","ISTL-REFERER", "https://www.sahibinden.com/",];
var originalBody = "";
function afterReadyCb() {
if (afterReadyCbCalled) return;
afterReadyCbCalled = true;
var xhr = new XMLHttpRequest();
xhr.onload = function() {
var isValid = xhr.getResponseHeader("ISTL-INFINITE-LOOP");
if (isValid != null && isValid != '') return;
var a = xhr.getResponseHeader("ISTL-REDIRECT-TO");
if (a != null && a != '') {
location.replace(a);
} else {
if (window.history != null && typeof history.replaceState === 'function') {
var responseURL = xhr.responseURL != null ? xhr.responseURL : xhr.getResponseHeader("ISTL-RESPONSE-URL");
if (responseURL != null && responseURL != '') {
history.replaceState(null, '', responseURL);
}
}
document.open();
document.write(xhr.responseText);
document.close();
}
};
xhr.open("get", location.href, true);
for (var i = 0; i < originalHeaders.length; i += 2) {
var headerName = originalHeaders[i];
try {
xhr.setRequestHeader(headerName, originalHeaders[i + 1]);
} catch (e) {}
}
xhr.setRequestHeader("ISTL-INFINITE-LOOP", '1');
xhr.send(originalBody);
var evt = document.createEvent('Event');
evt.initEvent('QLpZFJdHv', true, true);
dispatchEvent(evt);
}
addEventListener('afterReady', afterReadyCb, false);
setTimeout(afterReadyCb, 400);
}());
Code is extracted from website by simply saving the html. Here is the link to website : https://www.sahibinden.com/
Here a sample code:
function doScrapRequest (postData, onSuccessCallback, onErrorCallback) {
var options = {
hostname: "your-host-name",
port: 443,
path: "/path-you-want-to-post-to",
method: 'POST',
headers: {
'X-J3PopQvX-a': '0JMyqk3j...',
'X-J3PopQvX-b': '-1o1lvb'
'X-J3PopQvX-c': 'AEC_kwhy...'
'X-J3PopQvX-d': 'o_2'
'X-J3PopQvX-f': 'AyT1lA...'
'X-J3PopQvX-z': 'p'
}
};
var req = https.request(options, function (res) {
res.setEncoding('utf8');
var body = '';
res.on('data', function (chunk) {
body = body + chunk;
});
res.on('end',function(){
console.log("Body :" + body);
if (res.statusCode != 200) {
onErrorCallback("Api call failed with response code " + res.statusCode);
} else {
// If you are expecting application/json you can do JSON.parse in the body variable.
onSuccessCallback(body);
}
});
});
req.on('error', function (e) {
console.log("Error : " + e.message);
onErrorCallback(e);
});
// write data to request body
req.write(postData);
req.end();
}

TypeError: crypto.createCredentials is not a function

While authenticating with google i m getting this error:
TypeError: crypto.createCredentials is not a function
at exports.OAuth2._request (D:\WEB_D_CODING_NINJAS\Back-end\6.major\node_modules\oauth\lib\oauth2.js:33:22)
at exports.OAuth2.getOAuthAccessToken (D:\WEB_D_CODING_NINJAS\Back-end\6.major\node_modules\oauth\lib\oauth2.js:130:8)
at loaded (D:\WEB_D_CODING_NINJAS\Back-end\6.major\node_modules\passport-oauth2\lib\strategy.js:173:20)
at NullStore.verify (D:\WEB_D_CODING_NINJAS\Back-end\6.major\node_modules\passport-oauth2\lib\state\null.js:9:3)
at Strategy.OAuth2Strategy.authenticate (D:\WEB_D_CODING_NINJAS\Back-end\6.major\node_modules\passport-oauth2\lib\strategy.js:219:26)
at attempt (D:\WEB_D_CODING_NINJAS\Back-end\6.major\node_modules\passport\lib\middleware\authenticate.js:366:16)
at authenticate (D:\WEB_D_CODING_NINJAS\Back-end\6.major\node_modules\passport\lib\middleware\authenticate.js:367:7)
at Layer.handle [as handle_request] (D:\WEB_D_CODING_NINJAS\Back-end\6.major\node_modules\express\lib\router\layer.js:95:5)
at next (D:\WEB_D_CODING_NINJAS\Back-end\6.major\node_modules\express\lib\router\route.js:137:13)
at Route.dispatch (D:\WEB_D_CODING_NINJAS\Back-end\6.major\node_modules\express\lib\router\route.js:112:3)
at Layer.handle [as handle_request] (D:\WEB_D_CODING_NINJAS\Back-end\6.major\node_modules\express\lib\router\layer.js:95:5)
at D:\WEB_D_CODING_NINJAS\Back-end\6.major\node_modules\express\lib\router\index.js:281:22
at Function.process_params (D:\WEB_D_CODING_NINJAS\Back-end\6.major\node_modules\express\lib\router\index.js:335:12)
at next (D:\WEB_D_CODING_NINJAS\Back-end\6.major\node_modules\express\lib\router\index.js:275:10)
at Function.handle (D:\WEB_D_CODING_NINJAS\Back-end\6.major\node_modules\express\lib\router\index.js:174:3)
at router (D:\WEB_D_CODING_NINJAS\Back-end\6.major\node_modules\express\lib\router\index.js:47:12)
faced this doubt myself, took a lot of effort but finally, I figured it out, this is a problem because of your file in node modules read the error and reach here
node_modules\oauth\lib\oauth2.js:33 , on line 33 you will see that crypto.createCredentails command, I don't know why this file gets installed but change the code inside it
make it this one
var querystring= require('querystring'),
crypto= require('crypto'),
https= require('https'),
http= require('http'),
URL= require('url'),
OAuthUtils= require('./_utils');
exports.OAuth2= function(clientId, clientSecret, baseSite, authorizePath, accessTokenPath, customHeaders) {
this._clientId= clientId;
this._clientSecret= clientSecret;
this._baseSite= baseSite;
this._authorizeUrl= authorizePath || "/oauth/authorize";
this._accessTokenUrl= accessTokenPath || "/oauth/access_token";
this._accessTokenName= "access_token";
this._authMethod= "Bearer";
this._customHeaders = customHeaders || {};
this._useAuthorizationHeaderForGET= false;
//our agent
this._agent = undefined;
};
// Allows you to set an agent to use instead of the default HTTP or
// HTTPS agents. Useful when dealing with your own certificates.
exports.OAuth2.prototype.setAgent = function(agent) {
this._agent = agent;
};
// This 'hack' method is required for sites that don't use
// 'access_token' as the name of the access token (for requests).
// ( http://tools.ietf.org/html/draft-ietf-oauth-v2-16#section-7 )
// it isn't clear what the correct value should be atm, so allowing
// for specific (temporary?) override for now.
exports.OAuth2.prototype.setAccessTokenName= function ( name ) {
this._accessTokenName= name;
}
// Sets the authorization method for Authorization header.
// e.g. Authorization: Bearer <token> # "Bearer" is the authorization method.
exports.OAuth2.prototype.setAuthMethod = function ( authMethod ) {
this._authMethod = authMethod;
};
// If you use the OAuth2 exposed 'get' method (and don't construct your own _request call )
// this will specify whether to use an 'Authorize' header instead of passing the access_token as a query parameter
exports.OAuth2.prototype.useAuthorizationHeaderforGET = function(useIt) {
this._useAuthorizationHeaderForGET= useIt;
}
exports.OAuth2.prototype._getAccessTokenUrl= function() {
return this._baseSite + this._accessTokenUrl; /* + "?" + querystring.stringify(params); */
}
// Build the authorization header. In particular, build the part after the colon.
// e.g. Authorization: Bearer <token> # Build "Bearer <token>"
exports.OAuth2.prototype.buildAuthHeader= function(token) {
return this._authMethod + ' ' + token;
};
exports.OAuth2.prototype._chooseHttpLibrary= function( parsedUrl ) {
var http_library= https;
// As this is OAUth2, we *assume* https unless told explicitly otherwise.
if( parsedUrl.protocol != "https:" ) {
http_library= http;
}
return http_library;
};
exports.OAuth2.prototype._request= function(method, url, headers, post_body, access_token, callback) {
var parsedUrl= URL.parse( url, true );
if( parsedUrl.protocol == "https:" && !parsedUrl.port ) {
parsedUrl.port= 443;
}
var http_library= this._chooseHttpLibrary( parsedUrl );
var realHeaders= {};
for( var key in this._customHeaders ) {
realHeaders[key]= this._customHeaders[key];
}
if( headers ) {
for(var key in headers) {
realHeaders[key] = headers[key];
}
}
realHeaders['Host']= parsedUrl.host;
if (!realHeaders['User-Agent']) {
realHeaders['User-Agent'] = 'Node-oauth';
}
if( post_body ) {
if ( Buffer.isBuffer(post_body) ) {
realHeaders["Content-Length"]= post_body.length;
} else {
realHeaders["Content-Length"]= Buffer.byteLength(post_body);
}
} else {
realHeaders["Content-length"]= 0;
}
if( access_token && !('Authorization' in realHeaders)) {
if( ! parsedUrl.query ) parsedUrl.query= {};
parsedUrl.query[this._accessTokenName]= access_token;
}
var queryStr= querystring.stringify(parsedUrl.query);
if( queryStr ) queryStr= "?" + queryStr;
var options = {
host:parsedUrl.hostname,
port: parsedUrl.port,
path: parsedUrl.pathname + queryStr,
method: method,
headers: realHeaders
};
this._executeRequest( http_library, options, post_body, callback );
}
exports.OAuth2.prototype._executeRequest= function( http_library, options, post_body, callback ) {
// Some hosts *cough* google appear to close the connection early / send no content-length header
// allow this behaviour.
var allowEarlyClose= OAuthUtils.isAnEarlyCloseHost(options.host);
var callbackCalled= false;
function passBackControl( response, result ) {
if(!callbackCalled) {
callbackCalled=true;
if( !(response.statusCode >= 200 && response.statusCode <= 299) && (response.statusCode != 301) && (response.statusCode != 302) ) {
callback({ statusCode: response.statusCode, data: result });
} else {
callback(null, result, response);
}
}
}
var result= "";
//set the agent on the request options
if (this._agent) {
options.agent = this._agent;
}
var request = http_library.request(options);
request.on('response', function (response) {
response.on("data", function (chunk) {
result+= chunk
});
response.on("close", function (err) {
if( allowEarlyClose ) {
passBackControl( response, result );
}
});
response.addListener("end", function () {
passBackControl( response, result );
});
});
request.on('error', function(e) {
callbackCalled= true;
callback(e);
});
if( (options.method == 'POST' || options.method == 'PUT') && post_body ) {
request.write(post_body);
}
request.end();
}
exports.OAuth2.prototype.getAuthorizeUrl= function( params ) {
var params= params || {};
params['client_id'] = this._clientId;
return this._baseSite + this._authorizeUrl + "?" + querystring.stringify(params);
}
exports.OAuth2.prototype.getOAuthAccessToken= function(code, params, callback) {
var params= params || {};
params['client_id'] = this._clientId;
params['client_secret'] = this._clientSecret;
var codeParam = (params.grant_type === 'refresh_token') ? 'refresh_token' : 'code';
params[codeParam]= code;
var post_data= querystring.stringify( params );
var post_headers= {
'Content-Type': 'application/x-www-form-urlencoded'
};
this._request("POST", this._getAccessTokenUrl(), post_headers, post_data, null, function(error, data, response) {
if( error ) callback(error);
else {
var results;
try {
// As of http://tools.ietf.org/html/draft-ietf-oauth-v2-07
// responses should be in JSON
results= JSON.parse( data );
}
catch(e) {
// .... However both Facebook + Github currently use rev05 of the spec
// and neither seem to specify a content-type correctly in their response headers :(
// clients of these services will suffer a *minor* performance cost of the exception
// being thrown
results= querystring.parse( data );
}
var access_token= results["access_token"];
var refresh_token= results["refresh_token"];
delete results["refresh_token"];
callback(null, access_token, refresh_token, results); // callback results =-=
}
});
}
// Deprecated
exports.OAuth2.prototype.getProtectedResource= function(url, access_token, callback) {
this._request("GET", url, {}, "", access_token, callback );
}
exports.OAuth2.prototype.get= function(url, access_token, callback) {
if( this._useAuthorizationHeaderForGET ) {
var headers= {'Authorization': this.buildAuthHeader(access_token) }
access_token= null;
}
else {
headers= {};
}
this._request("GET", url, headers, "", access_token, callback );
}
after changing this file, google OAuth will work just fine

Streaming an Audio File over Node.js

I'm using node.js and torrent-stream to create a readable stream of a downloading audio file. I've piped this into an audio file in my directory.
My question is, how would I stream this audio file in node.js. Is there some standard way to play a file as it downloads?
I don't know of a way to play an audio file as it is downloaded, but here is some code that might work for what you are trying to do:
var http = require('http'),
fs = require('fs'),
filePath = 'myfile.mp3',
stat = fs.statSync(filePath);
http.createServer(function(request, response) {
response.writeHead(200, {
'Content-Type': 'audio/mpeg',
'Content-Length': stat.size
});
fs.createReadStream(filePath).pipe(response);
})
.listen(2000);
Hope this helps!
I tried this out and it seems to work:
const http = require('http')
const util = require('util')
const mime = require('mime')
const PORT = process.env.PORT || 8080
const onFinished = require('on-finished')
const parseRange = require('range-parser')
const torrentStream = require('torrent-stream')
const engine = torrentStream('magnet:?xt=urn:btih:b42f85d4d976f31d9edde30a101c79928e1353f6')
engine.on('ready', (files) => {
http.createServer(function (req, res) {
const index = parseInt(req.url.slice(1), 10)
if (!files.hasOwnProperty(index)) return res.end()
const file = files[index || 0]
console.log(`${file.name} ${req.headers.range ? req.headers.range : ''}`)
send(req, res, file)
}).listen(PORT, function () { console.log('Server listening on: http://localhost:%s', PORT) })
})
function send (req, res, file) {
let stream
let len = file.length
const type = mime.lookup(file.path)
if (type) {
const charset = mime.charsets.lookup(type)
res.setHeader('Content-Type', type + (charset ? '; charset=' + charset : ''))
}
res.setHeader('Content-Length', len)
res.setHeader('Accept-Ranges', 'bytes')
if (req.headers.range) {
const ranges = parseRange(len, req.headers.range, { combine: true })
if (ranges === -1) {
res.setHeader('Content-Length', 0)
res.setHeader('Content-Range', contentRange('bytes', len))
res.statusCode = 416
return res.end()
}
if (ranges !== -2 && ranges.length === 1) {
res.statusCode = 206
res.setHeader('Content-Range', contentRange('bytes', len, ranges[0]))
len = ranges[0].end - ranges[0].start + 1
res.setHeader('Content-Length', len)
if (req.method === 'HEAD') return res.end()
stream = file.createReadStream(ranges[0])
}
} else {
if (req.method === 'HEAD') return res.end()
stream = file.createReadStream()
}
onFinished(res, () => stream && stream.destroy())
stream.pipe(res)
return stream
}
function contentRange (type, size, range) {
return type + ' ' + (range ? range.start + '-' + range.end : '*') + '/' + size
}

Why does my server never receive any requests made inside of a loop in Node.js?

My code works fine outside of a loop:
var localFolder = '/home/transcripts',
apiHost = 'https://someserver'
apiCall = '/path',
sharedSecret = 'secret';
/* includes */
var sys = require('sys'),
fs = require('fs'),
exec = require('child_process').exec,
querystring = require('querystring'),
crypto = require('crypto')
request = require('request');
var file = "index_07_03_2013_1209576.csv";
console.log('Pushing CSV to API: ' + file);
var r = request.post(
apiHost + '/' + apiCall,
{ form: {
'filename': file,
'accessToken': crypto.createHash('md5').update(file + sharedSecret).digest('hex')
}
},
function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body);
}
console.log(error);
console.log(response);
}
);
file = "index_07_02_2013_1548773.csv";
console.log('Pushing CSV to API: ' + file);
var r = request.post(
apiHost + '/' + apiCall,
{ form: {
'filename': file,
'accessToken': crypto.createHash('md5').update(file + sharedSecret).digest('hex')
}
},
function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body);
}
console.log(error);
console.log(response);
}
);
file = "index_07_02_2013_1548773.csv";
console.log('Pushing CSV to API: ' + file);
var r = request.post(
apiHost + '/' + apiCall,
{ form: {
'filename': file,
'accessToken': crypto.createHash('md5').update(file + sharedSecret).digest('hex')
}
},
function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body);
}
console.log(error);
console.log(response);
}
);
However, when I try to move it into a forEach loop, no request is ever received by the server. I do see output indicating that the CSV file is being pushed to the API, but the request never seems to hit the server. Here's the code for that:
#!/usr/local/bin/node
/* environment vars */
var localFolder = '/home/transcripts',
apiHost = 'https://someserver'
apiCall = '/path',
sharedSecret = 'secret';
/* includes */
var sys = require('sys'),
fs = require('fs'),
exec = require('child_process').exec,
querystring = require('querystring'),
crypto = require('crypto')
request = require('request');
var counter = 0;
fs.readdir(localFolder, function(err, files) {
files.forEach(function(file) {
if (file.substr(-3, 3) == 'csv') {
console.log('Pushing CSV to API: ' + file);
request.post(
apiHost + '/' + apiCall,
{ form: {
'filename': file,
'accessToken': crypto.createHash('md5').update(file + sharedSecret).digest('hex')
}
},
function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body);
}
console.log(error);
console.log(response);
}
);
console.log(request);
}
counter++;
});
if (counter >= files.length) {
process.exit(0);
}
});
Anyone have any ideas what the problem might be?
I guess the looping version breaks because you run process.exit(0) as soon as counter >= files.length evaluates to true.
The reason it actually breaks the intended functionality is probably because you spin off the request calls (which are asynchronous) very fast, and once you've done that, you exit the program. My guess is that since you don't actually wait for the requests to finish (i.e. when the callbacks are done), you exit the program prematurely.
What you need is basically a wait group, and that you make sure not to exit your program before all the callbacks are done.
Try something like this:
// imports, etc
// ...
var counter = 0;
function done() {
counter--;
if(counter === 0) {
process.exit(0);
}
}
var callback = function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body);
}
console.log(error);
console.log(response);
done();
}
fs.readdir(localFolder, function(err, files) {
counter = files.length;
files.forEach(function(file) {
if (file.substr(-3, 3) == 'csv') {
console.log('Pushing CSV to API: ' + file);
var data = {
form: {
'filename': file,
'accessToken': crypto.createHash('md5').update(file + sharedSecret).digest('hex')
}
}
request.post(apiHost + '/' + apiCall, , data, callback);
}
}
);

Resources