I'm having trouble running a Node.js server with Adobe Brackets. Once in live preview (the URL is http://localhost:SOMERANDOMPORT/path/to/file.html), I start the server. If I type http://localhost:3000/test straight into another tab, it displays the correct JSON.
I then added an event function to an element in file.html that upon clicking it makes an AJAX request to my server and uses the response to change some of its inner HTML. However, clicking the element in live preview fails, and the error callback gets called instead.
How can I fix this? I suspect it has to do with the fact that the AJAX request sends to http://localhost:SOMERANDOMPORT/test rather than http://localhost:3000/test, but I can't seem to find a solution.
Everything runs locally. Below is my server:
var express = require('express');
var mysql = require('mysql');
var app = express();
app.get('/test', function(req, res){
var connection = mysql.createConnection(...);
connection.query("SELECT author FROM posts", function(err, results) {
if (err) {
console.log(err);
console.log('Error on retrieving data.');
res.send(err);
return;
}
console.log(results[results.length - 1]);
res.send(results[results.length - 1]); // return last row
});
connection.end();
});
app.listen(3000);
console.log('Listening on port ' + port);
And the event function:
function getAuthor() {
$.ajax({
type: 'GET',
url: '/test',,
success: function(data, status) {
$('.author').text('Authored by ' + data.author);
},
error: function(jqXHR, status, error) { // this always get called
$('.author').text('Something went wrong.');
}
});
}
I appreciate any help.
The simplest fix is to point Live Preview directly at your own Node server, letting it serve up the pages itself from the correct port number (rather than serving the pages from Brackets's built-in server that's on a different port). See instructions on the Brackets wiki under "Using your own backend."
The downside is that HTML live updating is disabled - but you'll still get CSS live updating, and Brackets falls back on a simpler "live reload" on save for HTML content.
To keep live HTML updating enabled you'd need to work around the port number difference somehow. You could hardcode a localhost:3000 base URL for testing, but you'll run same-origin problems due to the port numbers not matching. Working around that would be pretty involved (set up CORS on your Node server, etc.).
One other option for keeping the full Live Preview experience is to shim all your $.ajax() calls so they return hardcoded dummy data without hitting the server. If you're already doing some mocking for unit tests, you might be able to reuse that existing infrastructure for this.
Related
There are similar questions about it, but it's not very clear how to apply the solution, and keep to receive an error.
I explain. I'd like to create a simply html/js app using service worker technology.
I have:
Index.html
js/app.js
js/sw.js
in app.js the code is (see //*** comments to clearify):
// *** I receive always the error:
// *** ERROR: The path of the provided scope ('/') is not under the max scope allowed ('/js/').
// *** Adjust the scope, move the Service Worker script, or use the Service-Worker-Allowed HTTP header to allow the scope.
var headers = new Headers();
// *** I set the header in order to solve the error above:
// *** The value is set to "/" because this js is included in html file in upper folder.
// *** I tried even "../" and many more others values...
headers.append('Service-Worker-Allowed', '/');
console.log(headers.get('Service-Worker-Allowed'));
if ('serviceWorker' in navigator) {
console.log('Start trying Registrating Scope');
// *** I register the service worker.
// *** The path of service worker is "js/sw.js" because this js is included in html file in upper folder.
// *** The path of scope is "../" because is the path used by service worker, and I want it uses upper folder scope.
navigator.serviceWorker.register('js/sw.js', {scope: '../'})
.then(function(reg) {
// registration worked
console.log('Registration succeeded. Scope is ' + reg.scope);
})
.catch(function(error) {
// registration failed
console.log('Registration failed with ' + error);
});
console.log('End trying Registrating Scope');
}
As you see in the comment I still get the error "The path of the provided scope ('/') is not under the max scope allowed ('/js/'). Adjust the scope, move the Service Worker script, or use the Service-Worker-Allowed HTTP header to allow the scope."
Maybe I could move the sw.js file, but I'd like to know what's wrong.
Sure the problem is in how to register the header in the first 3 not commented lines of code.
Any advice of the code on how exactly register it?
EDIT:
What I'm missing is that what is to set is the request header, the header sent with the request, before asking the html page...
I'm creating headers, useful eventually for a future new request.
So js maybe is not the right place to put setting...
The setting must be setted before the request to index.html is made, because what's setted in the html or js is setted for the response, or prepared for other requests
now...
My approach now is to call another html page (register.html), in this page I'm tryng to $.ajax() the index.html page, with the right header setted:
(I now it could be done with pure js, but for time saving I copy/pasted some already tested code)
$(document).ready(function(){
$.ajax({
type: "GET",
beforeSend: function(request) {
request.setRequestHeader("Service-Worker-Allowed", "/");
},
url: "index.html",
complete: function () {
window.location = "index.html";
}
});
});
I was hoping the first time hit on ajax call I could register the service worker, then redirecting on complete on index.html, I could find it already registered, but event this doesn't work...
I repeat, quickest way is to move sw.js in upper folder. But it's interesting to know how to take control of how to register the service worker, despite of its position in tree folder application...
other advices...?
Ok... I was a little confused, and even now I guess I have to get deep in the facts and study http headers better...
Anyway as stated in many questions & answer on stackoverflow, it's not possible to alter headers during http request, unless it's not an ajax request (and that's not this case).
now on this post Understanding Service Worker scope for a similar question
#Ashraf Sabry answered he could alter the headers using web.config file of IIS Web Server. --> So finally I understood that the header to add is a response header, but before the response is interpreted by the browser --> As stated here https://learn.microsoft.com/en-us/iis/configuration/system.webserver/httpprotocol/customheaders/
that configuration is for response header.
I guess there is not clear way to control that header to make service worker doing his work in a subfolder using html/javascript... It's a problem that could be solved only with server configurations.
A was doing my tests on Node, for didactical porpouse I tried to write a simple http server to test this issue starting from this tutorial https://ilovecoding.org/lessons/create-a-simple-http-server-with-nodejs
the result is here (a "server.js" file runned on Node):
var http = require('http');
var url = require('url');
var querystring = require('querystring');
var fs = require('fs');
http.createServer(function(request, response){
pathName = url.parse(request.url).pathname;
console.log(pathName);
fs.readFile(__dirname + pathName, function(err, data){
if(err){
response.writeHead(404, {'Content-type':'text/plain'});
response.write('Page Was Not Found');
response.end();
}else{
if(pathName.endsWith(".html")){
//response.writeHead(200, {'Service-Worker-Allowed':'/', 'Content-Type':'text/html'});
response.writeHead(200, {'Content-Type':'text/html'});
console.log("serving html");
}else if(pathName.endsWith(".js")){
response.writeHead(200, {'Service-Worker-Allowed':'/', 'Content-Type':'application/javascript'});
//response.writeHead(200, {'Content-Type':'text/javascript'});
console.log("serving js");
}else if(pathName.endsWith(".css")){
//response.writeHead(200, {'Service-Worker-Allowed':'/', 'Content-Type':'text/css'});
response.writeHead(200, {'Content-Type':'text/css'});
console.log("serving css");
}else{
response.writeHead(200);
console.log("serving other");
}
response.write(data);
response.end();
}
})
}).listen(8080);
Using this js Node Server I could reach the same result stated for settings in IIS in the above link.
Note that after some test with this js, I reached that the file which needs "Service-Worker-Allowed:/" is the app.js file.
Now the application work as wanted returning no error.
As final prove tracing requests on fiddler I can clearly see the initial request for app.js, with "Service-Worker-Allowed: /" in the response;
My conclusion is that not always it is possible to handle server configuration, so putting service worker file on root folder of the app is the best approach.
Hope this could be helpful for some others...
the way I was able to register the worker with root scope was
navigator.serviceWorker.register(href = '/service_worker.js', { scope: '/' })
and the way I added the header was to make a new endpoint that served that service_worker file:
#app.route('/service_worker.js')
def service_worker():
from flask import make_response, send_from_directory
response = make_response(send_from_directory('static',filename='service_worker.js'))
response.headers['Content-Type'] = 'application/javascript'
response.headers['Service-Worker-Allowed'] = '/'
return response
Service Workers cannot control pages that do not fall within their scope. Service worker /js/sw.js cannot control page /index.html, because that html file does not exist in the /js/ folder (or subfolders of /js/). If you'd like /index.html to be controlled by a service worker, move the service worker to /sw.js.
It's easier to keep your code simple and put SWs in the proper folders (root if you manage the entire domain). This simplification avoids the unnecessary need to modify HTTP headers.
I want to get the content of a webpage by running javascript code on NodeJs . I want the content to be exactly the same as what I see in the browser.
This is the URL :
https://www.realtor.ca/Residential/Single-Family/17219235/2103-1185-THE-HIGH-STREET-Coquitlam-British-Columbia-V3B0A9
I use the following code but I get 405 in response.
var fs = require('fs');
var link = 'https://www.realtor.ca/Residential/Single-Family/17219235/2103-1185-THE-HIGH-STREET-Coquitlam-British-Columbia-V3B0A9';
var request = require('request');
request(link, function (error, response, body) {
fs.writeFile("realestatedata.html", body, function(err) {
if(err) {
console.log('error in saving the file');
return console.log(err);
}
console.log("The file was saved!");
});
})
The file which is saved is not related to what I can see in the browser.
I think a real answer will be easier to understand since my comment was truncated.
It seems the method of the request you send is not supported by the server (405 Method Not Allowed - The method specified in the Request-Line is not allowed for the resource identified by the Request-URI. The response MUST include an Allow header containing a list of valid methods for the requested resource.). Do you have more information about the HTTP response.
Have you tried the following code instead of yours ?
request('https://www.realtor.ca/Residential/Single-Family/17219235/2103-1185-THE-HIGH-STREET-Coquitlam-British-Columbia-V3B0A9').pipe(fs.createWriteStream('realestatedata.html'))
You could also have a look at In Node.js / Express, how do I "download" a page and gets its HTML?.
Note that anyway the page will not render the same way when you only open the html since it also requires many other resources (110 requests are done when display the page).
I think the following answer can help you to download the whole page.
https://stackoverflow.com/a/34935427/1630604
I'm running a small Angular application with a Node/Express backend.
In one of my Angular factories (i.e. on the client side) I make a $http request to Github to return user info. However, a Github-generated key (which is meant to be kept secret) is required to do this.
I know I can't use process.env.XYZ on the client side. I'm wondering how I could keep this api key a secret? Do I have to make the request on the back end instead? If so, how do I transfer the returned Github data to the front end?
Sorry if this seems simplistic but I am a relative novice, so any clear responses with code examples would be much appreciated. Thank you
Unfortunately you have to proxy the request on your backend to keep the key secret. (I am assuming that you need some user data that is unavailable via an unauthenticated request like https://api.github.com/users/rsp?callback=foo because otherwise you wouldn't need to use API keys in the first place - but you didn't say specifically what you need to do so it is just my guess).
What you can do is something like this: In your backend you can add a new route for your frontend just for getting the info. It can do whatever you need - using or not any secret API keys, verify the request, process the response before returning to your client etc.
Example:
var app = require('express')();
app.get('/github-user/:user', function (req, res) {
getUser(req.params.user, function (err, data) {
if (err) res.json({error: "Some error"});
else res.json(data);
});
});
function getUser(user, callback) {
// a stub function that should do something more
if (!user) callback("Error");
else callback(null, {user:user, name:"The user "+user});
}
app.listen(3000, function () {
console.log('Listening on port 3000');
});
In this example you can get the user info at:
http://localhost:3000/github-user/abc
The function getUser should make an actual request to GitHub and before you call it you can change if that is really your frontend that is making the request e.g. by cheching the "Referer" header or other things, validate the input etc.
Now, if you only need a public info then you may be able to use a public JSON-P API like this - an example using jQuery to make things simple:
var user = prompt("User name:");
var req = $.getJSON('https://api.github.com/users/'+user);
req.then(function (data) {
console.log(data);
});
See DEMO
I am new to Node.js and this is my first project with it.
I have made a node.js file named test.js. It has an array say a.
Now I want to make a HTML file that calls this test.js on button click event. Then get the data from that file and publish it on a table in the HTML file.
I have already written the node.js file and I can see the results on console.log(a). But I cant understand how to send this array to HTML when it will ask for it.
Meanwhile, I googled and made up some code. The request reaches the server but I always get error response from server. Why so?
Client Side -
function fetch() {
$.ajax({
type: 'POST',
url: "http://127.0.0.1:8888",
data: 'China',
datatype: 'json',
success: function (data) {
alert("hi");
var ret = jQuery.parseJSON(data);
$('#q').html(ret.msg);
},
error: function (xhr, status, error) {
alert("hii");
}
});
Server side :
http.createServer(function(request, response) {
console.log("Request received");
response.writeHeader(200, {"Content-Type": "application/json"});
request.on('data', function (chunk) {
console.log(chunk.toString('utf8'));
consol.log(result);
response.write(JSON.stringify({data : result}));
});
response.end();
}).listen(8888);
I can see China on the console.But I dont get back the result array back to the client. Here result is an array and I get its value on the console. Just that I dont get it back to the client. Any help ?
You should start by setting up a server to serve requests. I use expressjs for this - http://expressjs.com/
This will allow you to run nodejs as a web application.
Setup a route in express JS to serve your data - http://expressjs.com/api.html#express
var express = require('express');
var app = express();
app.get('/data', function(req, res){
res.send('hello world'); //replace with your data here
});
app.listen(3000);
Open up a browser, and type in http://MY_SERVER_ADDR:3000/data and you should see your output there.
Next, you'll need to attach an event handler to your HTML file that will trigger a $.get() request when it is triggered. Add the previous url to your data in your $.get call and do something with it.
$('.my_selector').click(function(){
$.get('http://MY_SERVER_ADDR:3000/data', {}, function(data){
console.log(data)
});
});
That should get you going.
After wrestling with the same question, i found that this is exactly where a template engine comes into the node-picture.
EJS solved it for me, but there are many more available.
This article compares 10 template engines.
I'm creating a reverse HTTP proxy using Node.js for fun. The code is pretty simple at the moment. It listens on 127.0.0.1:8080 for HTTP requests and forwards these to hostname.com, responses from hostname.com are then forwarded back to the client. Nothing fancy is done yet such as rewriting redirect headers, etc. The code is as follows:
var http = require('http');
var server = http.createServer(
function(request, response) {
var proxy = http.createClient(8080, 'hostname.com')
var proxyRequest = proxy.request(request.method, request.url, request.headers);
proxyRequest.on('response', function(proxyResponse) {
proxyResponse.on('data', function(chunk) {
response.write(chunk, 'binary');
});
proxyResponse.on('end', function() {
response.end();
});
response.writeHead(proxyResponse.statusCode, proxyResponse.headers);
});
request.on('data', function(chunk) {
proxyRequest.write(chunk, 'binary');
});
request.on('end', function() {
proxyRequest.end();
});
proxyRequest.on('close', function(err) {
if (err) {
console.log('close error: ' + err + ' for ' + request.url);
}
});
});
server.listen(8080);
server.on('clientError', function(exception) {
console.log('boo a clientError occured :(');
});
All appears to work well until I browse to a page that requires many additional resources (such as images) to be fetched. Naturally the browser will generate a number of GET requests to the reverse proxy to fetch these additional resources.
When I do browse to such a page some of the http.ServerRequests for the additional resources never receive responses. If I restart the page request it almost always results in success as all the resources that were successfully fetched on the first attempt were cached (hence the browser doesn't try GET them again) and so now the browser only needs to grab a few missing ones.
At a guess I would imagine I'm hitting some kind of connection limit although I'm not sure. Any help would be greatly appreciated!
If you set up Wireshark on the proxy, you'll almost certainly see what's happening. (Note that you may need a second machine for this, because some TCP/IP stacks don't provide anything that Wireshark can listen on for loopback traffic - see this)
I'm almost certain that the problem(s) you are running into here are all down to the Connection: header - proxies MUST parse this header and handle it correctly. At a guess, I would say your code is handling the first request in a Connection: keep-alive stream and ignoring the rest. As a proxy, you are supposed to parse and remove/replace this header, and any associated headers (in this case the Keep-Alive: header), before forwarding the request to the server.
If you want to build a HTTP/1.1 proxy, it's very important that you read RFC 2616 and adhere to the many, many rules that it places on their behaviour. The particular problem you are running into here is documented in section 14.10.