Failing to fetch my local API running in localhost (Amazon Cloud 9) - javascript

I have a simple flask server that returns a JSON (flask automatically do that when you return a python dict) when it receives a GET request to / endpoint.
It's running on my 5000 port:
I know it's running and reachable as I managed to request to it, and receive a valid response, using curl, twice:
Both requests are logged into the server logs as well, on second print.
I'm trying to fetch to my server from a html/js script as:
const URL = "http://127.0.0.1:5000/"
fetch( URL )
.then(response=>response.json())
.then(json=>console.log(json))
or
const URL = "http://localhost:5000/"
fetch( URL )
.then(response=>response.json())
.then(json=>console.log(json))
But I get the same error twice:
1: GET http://localhost:5000/ net::ERR_CONNECTION_REFUSED
2: Uncaught (in promise) TypeError: Failed to fetch
I know the code itself works because I managed to fetch Githubs API:
const URL = "https://api.github.com/users/nluizsoliveira"
fetch( URL )
.then(response=>response.json())
.then(json=>console.log(json))
I'm not sure why I can't fetch to my localhost. I think it has something to do with how cloud9 deals with ports. When removing http://localhost from the url:
const URL = ":5000"
fetch( URL )
.then(response=>response.json())
.then(json=>console.log(json))
the snippet also fails, but it seems that the request is somehow appending the url to my C9 url.
Have someone faced that situation before?
Thanks a lot in advance!
EDIT:
Just to clarify, i'm not running that js/html (directly) on my browser tab. I'm running it on the C9's built in browser, which is available through "preview running application":

With AWS Cloud 9 Preview, AWS gives you a private link like https://12a34567b8cd9012345ef67abcd890e1.vfs.cloud9.us-east-2.amazonaws.com which gives you access to your application. To get that link click preview application and copy it from the browser tab.
Use that link in your code instead of localhost. AWS Documentation:Preview a running application.

Related

Download and save MJPEG with http command (Javascript)

I'm using a hikvision IP camera that streams 30 MJPEG images per second to a certain http url and Javascript Reactjs with nodejs and express as backend.
Also hikvision provides a url to snap the camera image when you open the link.
Example link:
http://192.168.0.109/ISAPI/Streaming/channels/1/picture
I want to download that image and store it as a local file on my computer, I know how to store it but I haven't been able to download the image programatically.
I followed the next guide to get those API endpoints (stream and snapshot):
HIKVISION TUTORIAL
My question is, how do I fetch or download that image ?
I have tried with fetch without success.
Not sure but as long as I understand it requires a basic digest authorization and I haven't find how to fetch with digest auth. If I open the link directly on my browser, a pop up prompts and ask me for my username and password.
Everytime I try to fetch the response is :
GET http://192.168.0.109/ISAPI/Streaming/channels/1/picture net::ERR_ABORTED 401 (Unauthorized)
There is also some parameters to this API command on documentation that includes a json format that I have tried without success:
Also, as you can see on HIKVISION TUTORIAL there is an url to get the stream, I'm able to reproduce that MJPEG stream on front-end with the next code with no issues:
<img
width={"90%"}
height={"60%"}
alt="stream"
src={"http://192.168.0.109/ISAPI/Streaming/channels/102/httpPreview"}
id="cam1"
/>
net::ERR_ABORTED 401 (Unauthorized)
Based on the error you presented, I suspect that you have set a username/password.
The documentation (that you linked to in your question) explains that if you have set a username/password, then you need to use Basic auth:
http://<username>:<password>#<IP address of IPC>:<HTTP
port>/ISAPI/Streaming/channels/1/picture
So, if the local IP address that you're using is 192.168.0.109, then the URL format would be:
http://<username>:<password>#192.168.0.109/ISAPI/Streaming/channels/1/picture
and <username> and <password> would be your actual username and password.
Note that this URL format is deprecated in many environments. You can send the auth data in the request headers instead:
function setBasicAuthHeader (headers, username, password) {
// In Node:
const encoded = Buffer.from(`${username}:${password}`).toString('base64');
// In a browser/deno:
// const encoded = window.btoa(`${username}:${password}`);
headers.set('Authorization', `Basic ${encoded}`);
}
const username = 'me';
const password = 'secret';
const headers = new Headers();
setBasicAuthHeader(headers, username, password));
// Use headers in your request...

How are URIs containing umlaut vowels (like ä, ö and ü) encoded in axios?

I've stumbled across some weird behaviour while using axios to fetch files from an
external endpoint.
The endpoints url looks something like this: https://example.com/path/to/file/filename.pdf
When accessing the url using the browser, a download dialog would pop up and request a confirmation in order to download the file.
While this simple GET request seemed to work fine, doing the same using axios did not.
const res = await axios.get("https://example.com/path/to/file/filename.pdf", { responseType: "blob" }); // throws a 400 error
After doing some further digging I decided to try out requesting the url from the same machine using python - this worked without an issue.
import requests
url = 'https://example.com/path/to/file/filename.pdf'
r = requests.get(url)
open('test.pdf', 'wb').write(r.content)
The solution
After some (more) frustration and searching the web for issues without any success I've finally discovered the issue and its solution.
The issue only occured when the filename in the specified url included german characters such as ä, ö or ü. Passing the URL to encodeURI and then calling axios with the returned value did the trick.
const res = await axios.get(encodeURI("https://example.com/path/to/file/filenäme.pdf"), { responseType: "blob" }); // works even with ä, ö, ü in the url
The remaining question
The question that remains is why? Checking the outgoing network requests reveals that the requests seem to go to the same url, meaning the URL in chromes network tab always looked the same. The filename "Lösung" was encoded to be "L%C3%B6sung", no matter if the request was run using the browser, a webpage (axios in the browser), a Node app (axios /w node) or Python. Still, axios seems to handle the encoding different to the other methods.
Perhaps Chromes Network tools parse the displayed url too, meaning the actual request was sent to /Lösung.pdf but was displayed as /L%C3%B6sung.pdf while viewing the outgoing network requests? Is there a setting for URL parsing in the axios configuration I might have missed?

How to use CORS in javascript to get response from Dialogflow (Api.Ai)

Since last couple of hours when I try to connect api.ai using javascript I get the following error .
"Failed to load https://api.api.ai/v1/query?v=20150910: No 'Access-Control-Allow-Origin' header is present on the requested resource."
I try to send request to Api.AI using javascript by following way:-
const client = new ApiAi.ApiAiClient({
accessToken: "*******************"
});
const promise = client.textRequest(query);
promise
.then(handleResponse)
.catch(handleError);
function handleResponse(serverResponse) {}
You can use browser Extension for this problem.
In chrome
If you use PostMan or other service except browser you don't see this error or you can use nginx proxy to get result.
I too have started facing this issue from few hours, it looks like people at DialogFlow have changed the CORS restrictions.
Right now, only solution is to use a middle proxy server / cloud function which will call the api.ai url on behalf of browser and send the result back to browser.
Found the issue and answer here.
I guess you are calling the API from the browser. It is not a great option here as anyone can see your access code.
You can try the following solutions:
Call the API from the back-end - not front-end.
Use fetch API and disable CORS.

Http request error with codeSandBox (React/Node)

I have strange error in online IDE like CodeSandBox/StackBlitz.
I do a sample http request (with axios but with fetch or others the problem is the same) and try to print the response in the console.
I use React for the front and node (listen port 8080) for the back,
I precise that work when I do exactly the same with create react app, using npm start (localhost:3000 and http request in http://[public ip]:8080/coucou)
react code here (request is in the Main.js file):
https://codesandbox.io/s/ww28ry45pl
When I just put http://[public ip]:8080/coucou that work to and I have the good response from server.
Here the error returned by server in codeSandBox (captured by the catch bloc) :
Error {stack:
"createError#https://ww28ry45pl.codesandbox.io/node_modules/axios/lib/core/createError.js:16:15
handleError#https://ww28ry45pl.codesandbox.io/node_modules/axios/lib/adapters/xhr.js:87:14
"}
I haven't found anything about this problem.
This is because you are making an HTTP call from a secure communication point (codesandbox). You can simply use/add https on your public URL and it shall work. HTTP Ajax Request via HTTPS Page
In my case I was calling Localhost from codesandbox in https. I solved it by Enabling CORS handling on my localhost server.
Just try again without http:// prefix in the URL. I solved same error :)

NodeJS: Send HTTPS request but get HTTP

I am building a website using NodeJS, and I deploy it to Heroku. But when I open the website, something went wrong. Here is the problem:
Code:
In the main source file of my web:
app.get('/', (req, res) => {
var data = {
rootURL: `${req.protocol}://${req.get('Host')}`,
};
res.render('home.html', data);
});
Then, in home.html, I include the following script:
<script type="text/javascript">
$.getJSON('{{rootURL}}'+'/about', {}, function(data){
// Code here is deleted for now.
}).fail(function(evt) {
// Code here is deleted for now.
});
</script>
Here I use hbs template, so {{rootURL}} is equal to the 'rootURL' property within the 'data' object rendered along with the 'home.html' page.
The '/about' is one of the APIs I designed for my web. It basically sends back something about the website itself and this information is wrapped in JSON.
Then, here comes the problem. The code works fine locally, and works well when I send HTTP request instead of HTTPS to Heroku. But if I send HTTPS request to Heroku, I'll get 'Mixed Content' Errors:
Errors I get in Chrome Console.
I then switched to 'Elements' tab in the developers tool, and I saw this:
The schema is HTTP, not HTTPS!
I'm very confused here. I just grab the 'protocol' property within the 'req' object, and fill in the template with it. So, I'm assuming if I enter '[my-website-name].herokuapp.com' with 'https' schema in my Chrome Browser, my nodeJS app deployed on Heroku should get 'https' for req.protocol. But Apparently it's not the case. What is wrong here?
I assume you don't actually have an SSL certificate? Heroku will be providing the HTTPS, but it will then translate it to normal HTTP internally when it hits your express endpoint, which is why it sees req.protocol as HTTP.
Is there any point in even providing the URL to getJSON? Why not just send it $.getJSON('/about', callback) and let the browser handle that?
Also, you haven't hidden your URL in that first image you uploaded, if that's what you were intending.
Heroku router is doing SSL termination, so no matter if you connect via http or https, you get http on your side. Original protocol is however set in X-Forward-Proto header. You need use this value.

Categories

Resources