My goal is to intercept every outgoing message from my server in a meteor project and add some stuff (meta datas and additional contents)
I have this simple code :
var http = Npm.require( 'http' ),
originalWrite = http.OutgoingMessage.prototype.write;
http.OutgoingMessage.prototype.write = function ( chunk, encoding ) {
console.log( this, arguments );
chunk = chunk.replace( 'some code', 'elements to add' );
originalWrite.call( this, chunk, encoding );
}
It works but I cannot find the url of the current call. This is a problem because I need to add different elements according to the called url.
(nota : I have a condition to make sure the request is an html file)
The full URL isn't directly available but host and path are through the request header Host and a property path on the OutgoingMessage object.
To obtain the full URL:
var url = this.getHeader('host') + this.path; //or this._headers.host;
--
var originalWrite = http.OutgoingMessage.prototype.write;
http.OutgoingMessage.prototype.write = function () {
var url = this.getHeader('host') + this.path;
//...
return originalWrite.apply(this, arguments);
};
The reason path isn't available in the header is because the request path is part of the Request-Line. The OutgoingMessage implementation first establishes a TCP connection to the host and then issues a request on the path.
GET /path HTTP/1.1
Host: hostname
Related
I was going through the following article :
https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Fetching_data
Here , the concept of AJAX is being illustrated however , for simple illustration ,instead of connecting to the server ,the content is being fetched from the system which has the browser in it .
So in the following code lines from the above mentioned link :
var url = verse + '.txt';
var request = new XMLHttpRequest();
request.open('GET', url);
Here a GET verb is to fetch the contents of the file in the local system and no server is present there .
Similarly , by using javascript and in the absence of a server
can we add some parameters to GET or POST verb and run a code in the local system which processes these parameters and sends an output .
Like :
var url = 'verse + '.txt' + '?' 'name = ' + 'vim' ; //Adding parameters
and there will be some javascript file , which takes these parameter "name "
and returns it in uppercase , like "VIM " .
Can we do anything like that using Javascript only (not nodejs or anything that sets up a server " ) without server listening ?
To achieve the requirement you can use Chromium or Chrome browser launched with --allow-file-access-from-files flag set.
fetch() does not permit requesting local files having file: protocol, though XMLHttpRequest() does. fetch() does allow requesting data URL and Blob URL.
For
some javascript file , which takes these parameter "name " and returns
it in uppercase , like "VIM "
Worker can be used to get the contents of a local file, manipulate the content, then postMessage() can be called to communicate with main thread.
For example
worker.js
onmessage = e => {
// do stuff
let url = new URL(e.data);
let [[,param]] = [...url.searchParams]; // get query string parameter `'vim'`
let request = new XMLHttpRequest();
request.open('GET', 'file:///path/to/local/file' /* e.data */);
request.onload = e => {
console.log(request.responseText); // `setTimeout()` can be inside `load` handler
}
request.send();
// asynchronous response
setTimeout(() => {
// set `data URL` that `fetch()` will request
postMessage(`data:text/plain,${param.toUpperCase()}`);
}, Math.floor(Math.random() * 2000));
}
At console or within a script
const localRequest = async(url) => {
const request = await fetch(await new Promise(resolve => {
const worker = new Worker('worker.js');
worker.onmessage = e => {
resolve(e.data);
worker.terminate();
}
worker.postMessage(url);
}));
const response = await request.text();
console.log(response);
}
localRequest('file:///verse.txt?name=vim');
I am wondering how to accomplish the below with Django:
Consider a function in JavaScript:
$('#button').click(function(){
var rand_val = Math.random();
// here some code sends this rand_val to a Python script in Django app
// as seen below, script is run and generates result
alert('This is the result ' + result);
})
The script in the Django app:
def my_func(rand_val):
# result = (some operations with rand_val)
return result
The Python script will be run in Django virtual environment.
With a button click, run a Python script and show the result on the page.
You can send the data with ajax get,
var url = "url_to_my_func_view/" + rand_val
$.get( url, function( data ) {
alert( "Data Loaded: " + data );
});
You will need to return your result as bytes or JSON using HttpResponse or JsonResponse.
Edit:
If you need to send back user input (as the OP explained in the comments), then you are better off with GET or POST params. In JS you would do like so,
var url = 'url_to_my_func_view/'
$.get( url, {'user_val': rand_val}, function( data ) {
alert( "Data Loaded: " + data );
});
Then in your view you would catch those params like so,
def my_func(request):
user_val = request.GET['user_val']
return user_val
Notice that your function receives a request!
Hope this helps!
To perform form submission through Ajax, need to use some specific code snippets. I am adding the details source code so, you might find these helpful!
The code in JavaScript file:
//The functions below will create a header with csrftoken for Ajax based submission in Django application
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
function sameOrigin(url) {
// test that a given url is a same-origin URL
// url could be relative or scheme relative or absolute
var host = document.location.host; // host + port
var protocol = document.location.protocol;
var sr_origin = '//' + host;
var origin = protocol + sr_origin;
// Allow absolute or scheme relative URLs to same origin
return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
(url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
// or any other URL that isn't scheme relative or absolute i.e relative.
!(/^(\/\/|http:|https:).*/.test(url));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && sameOrigin(settings.url)) {
// Send the token to same-origin, relative URLs only.
// Send the token only if the method warrants CSRF protection
// Using the CSRFToken value acquired earlier
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
// Ajax setup end
$('#button').click(function(e){
var rand_val = Math.random();
$.post('/my_func/', { rand_val: rand_val }, function(data){
return false;
});
e.preventDefault();
});
In views.py:
def my_func(request):
response = {}
if request.method == 'POST':
rand_val = request.POST.get('rand_val')
# result = (some operations with rand_val)
return result
In urls.py: Django v2.x
from django.contrib import admin
from django.urls import path, include
import APP_NAME.views
urlpatterns = [
path('my_func/', APP_NAME.views.my_func),
]
Expecting the code will work for you!
I'm using nodejs with node-http-proxy along with harmon. I am using harmon to rewrite the proxied response to include a javascript file and a css file. When I set the target of the proxy to be http://nodejs.org or anything other than localhost, I receive a 301 or 302 redirect. The script is rewriting the 301 response instead of the fully proxied response. How can I use harmon to rewrite the end response instead of the 302 response?
Here is the example of the script I am running from the harmon example folder:
var http = require('http');
var connect = require('connect');
var httpProxy = require('http-proxy');
var selects = [];
var simpleselect = {};
//<img id="logo" src="/images/logo.svg" alt="node.js">
simpleselect.query = 'img';
simpleselect.func = function (node) {
//Create a read/write stream wit the outer option
//so we get the full tag and we can replace it
var stm = node.createStream({ "outer" : true });
//variable to hold all the info from the data events
var tag = '';
//collect all the data in the stream
stm.on('data', function(data) {
tag += data;
});
//When the read side of the stream has ended..
stm.on('end', function() {
//Print out the tag you can also parse it or regex if you want
process.stdout.write('tag: ' + tag + '\n');
process.stdout.write('end: ' + node.name + '\n');
//Now on the write side of the stream write some data using .end()
//N.B. if end isn't called it will just hang.
stm.end('<img id="logo" src="http://i.imgur.com/LKShxfc.gif" alt="node.js">');
});
}
selects.push(simpleselect);
//
// Basic Connect App
//
var app = connect();
var proxy = httpProxy.createProxyServer({
target: 'http://nodejs.org'
})
app.use(require('../')([], selects, true));
app.use(
function (req, res) {
proxy.web(req, res);
}
);
The problem is that a lot of sites are now redirecting HTTP to HTTPS.
nodejs.org is one of those.
I have updated the sample https://github.com/No9/harmon/blob/master/examples/doge.js to show how the http-proxy needs to be configured to deal with HTTPS.
If you still have problems with other arbitrary redirects please log an issue on harmon.
Thanks
I have the following code, and node.js can't resolve the url:
const request = require('request')
const teamURL = `/users/${user._id}/teams`;
const req = request({
url: teamURL,
json: true
},
function(error, response, body) {
if (!error && response.statusCode == '200') {
res.render('userHome.html', {
user: user,
teams: body
});
}
else {
console.error(error);
next(error);
}
});
is there a good way to use relative paths/urls with the request library on a server-side node.js Express app?
Giving just a relative url only works if it is clear from context what the root part of the url should be. For instance, if you are on stackoverflow.com and find a link /questions, it's clear from context the full url should be stackoverflow.com/questions.
The request library doesn't have this kind of context information available, so it needs the full url from you to do be able to make the request. You can build the full url yourself of course, for instance by using url.resolve():
var url = require('url');
var fullUrl = url.resolve('http://somesite.com', '/users/15/teams');
console.log(fullUrl); //=> 'http://somesite.com/users/15/teams');
But of course this will still require you to know the root part of the url.
Jasper 's answer is correct -- the request module needs full URL. if you are in a situation where you have a single page application, with lots of requests to an API with the same base URL, you can save a lot of typing by creating a module like this:
var url = require('url');
var requestParser = (function() {
var href = document.location.href;
var urlObj = url.parse(href, true);
return {
href,
urlObj,
getQueryStringValue: (key) => {
let value = ((urlObj && urlObj.query) && urlObj.query[key]) || null;
return value;
},
uriMinusPath: urlObj.protocol + '//' + urlObj.hostname
};
})();
then, to grab the base URL anytime you need it: requestParser.uriMinusPath
and grab the value of an arbitrary query parameter: RequestParser.getQueryStringValue('partner_key');
I am developing an extension in which whatever request is coming i want to change the request parameters and send a dummy request to server to get response.
for eg. if original request loaded is www.abc.com/eg.php?user="some code", then i want to change it into www.abc.com/eg.php?user="ritubala" and get html page in the response for further processing inside my extension..
i used these codes given in following url
Return HTML content as a string, given URL. Javascript Function
but it is causing recursion...
so in short i want to get html code from a url inside my extension...plz do help
Use nsITraceableChannel, note that you get a copy of the content being loaded.
If you abort the request then it aborts giving you a copy.
Here's me using nsITraceableChannel: https://github.com/Noitidart/demo-nsITraceableChannel
What I think you want is this:
const { Ci, Cu, Cc, Cr } = require('chrome'); //const {interfaces: Ci, utils: Cu, classes: Cc, results: Cr } = Components;
Cu.import('resource://gre/modules/Services.jsm');
Cu.import('resource://gre/modules/devtools/Console.jsm');
var observers = {
'http-on-examine-response': {
observe: function (aSubject, aTopic, aData) {
console.info('http-on-modify-request: aSubject = ' + aSubject + ' | aTopic = ' + aTopic + ' | aData = ' + aData);
var httpChannel = subject.QueryInterface(Ci.nsIHttpChannel);
var requestUrl = httpChannel.URI.spec
if (requestUrl.indexOf('blah')) {
//httpChannel.cancel(Cr.NS_BINDING_ABORTED); //this is how you abort but if use redirectTo you don't need to abort the request
httpChannel.redirectTo(Services.io.newURI('http://www.anotherwebsite/', null, null));
}
},
reg: function () {
Services.obs.addObserver(observers['http-on-modify-request'], 'http-on-modify-request', false);
},
unreg: function () {
Services.obs.removeObserver(observers['http-on-modify-request'], 'http-on-modify-request');
}
}
};
//register all observers
for (var o in observers) {
observers[o].reg();
}
note the redirectTo function is for FF20+
https://developer.mozilla.org/en-US/docs/XPCOM_Interface_Reference/nsIHttpChannel#redirectTo%28%29
so combine this example with the nsITraceableChannel demo and you'll have what you want.
if you don't want to redirect you can abort the request, get the DOCUMENT of the request and then xmlhttprequest the new page which gives you the source FIRST and doesnt load it to tab, and then modify the source then load it back to the DOCUMENT.
OR instead of xmlhttprequesting it, just abort the request, redirectTo the new page and then modify the tab. to get the tab of the channel see solution here:
Security Error when trying to load content from resource in a Firefox Addon (SDK)
also to do http requests from an extension see this snippet: https://gist.github.com/Noitidart/9088113