In my HTML file, I have a single line (below) that gets a response from a device over WiFi & makes data available to my JavaScript, it works well except when there is an error in the response text & it halts.
<script type="text/javascript" src="http://192.168.4.1/"></script>
The response is a text string representing JavaScript variables, it sometimes gets corrupted throwing an error.
Examples:
Uncaught SyntaxError: invalid assignment left-hand side 192.168.4.1:14:3
SyntaxError: unterminated string literal 192.168.4.1:3:8
I need a solution to capture the error of parsing the received string so I can run the above statement again to get a new string.
Thanks
below is a picture of the response string (JS variables.)
The issue is that once the script is loaded, its content might be misformed and I would like to avoid having errors due to that.
Update #1. get the data with XMLHttpRequest
<script>
const Http = new XMLHttpRequest();
const url='http://192.168.4.1/';
Http.open("GET", url);
// Http.setRequestHeader('Access-Control-Allow-Origin', '*');
Http.send();
ReturnVar = Http.responseText
Http.onreadystatechange = (e) => { console.log(Http.responseText) }
</script>
Below is the detail in browser Console, Headers after script above run.
GET
scheme http
host 192.168.4.1
filename /
Address 192.168.4.1:80
Transferred 1.82 KB (1.82 KB size
Request headers (278B)
GET /
Host: 192.168.4.1
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:81.0) Gecko/20100101 Firefox/81.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Origin: null
DNT: 1
Connection: keep-alive
Cache-Control: max-age=0
You have a script tag, which is loading the script and evaluating its content. You need to programmatically modify this, so you need to
Get the file as a text
https://www.freecodecamp.org/news/here-is-the-most-popular-ways-to-make-an-http-request-in-javascript-954ce8c95aaa/
You just need to programmatically download the content the file, not as the src of a script.
Evaluate it
Before you proceed, read this: https://javascriptweblog.wordpress.com/2010/04/19/how-evil-is-eval/
Now, that you know that eval is not exactly popular - and rightly so - and if you are still sure you need to run a script as it is, study eval and make it work equivalently as it was
Encapsulate it into try-catch
Example for error:
eval("'");
Example for error in try-catch:
try {eval("'")} catch (ex) {}
you can call the address using ajax, and then if the response is in json you can easily use it, but if its some sort of script or something else, wrap it in a script tag an append it to the body.
assume the result is what you got from ajax request and you have jQuery in your project:
$('body').append('<script>'+result+'</script>')
in this case you can wrap your code in try catch and handle the errors
Related
I hope this is not a duplicate...
I am trying to POST user email & password to a php file and it seems that the php file isn't getting those values.
The js code:
function ReceiveLoginData() {
let text = this.responseText;
console.log(text);
let json_data = JSON.parse(
text.substring(1, text.length - 1).replaceAll("\\u0022", "\"")
);
// there is a lot more code... but its irrelevant.
}
function SubmitLogin() {
var email_addr = document.getElementsByClassName("login-email")[0].value;
var passwd = document.getElementsByClassName("login-passwd")[0].value;
var req = new XMLHttpRequest();
req.onload = ReceiveLoginData;
// req.onreadystatechange = ReceiveLoginData; // does not work...
req.open("POST", "/users/auth/login.php"); // ...,true); or ...,false); fail too...
req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
let data_to_send = "uemail=" +
window.encodeURIComponent(email_addr) +
"&upasswd=" +
window.encodeURIComponent(passwd);
// data_to_send = "uemail="+email_addr ... works neither
req.send(data_to_send);
}
PHP (actually its location is localhost:4000/users/auth/login.php)
<?php
$uemail = $_POST["uemail"];
$upasswd = $_POST["upasswd"];
$login_err = true;
// set it to false otherwise
function SendData(string $str)
{
echo json_encode($str, JSON_HEX_QUOT | JSON_HEX_APOS);
}
function main_fn()
{
$uemail = strtolower($uemail);
if (strlen($uemail) == 0) {
SendData("[\"noemail\"]");
}
// and much more but again irrelevant...
}
main_fn();
?>
I learnt that using window.encodeURIComponent(...) is safer from here: https://stackoverflow.com/a/17382629/18243229
but neither of the ways work.
Whatever I got to know after literal 5 hours of debugging and getting fed up(I blame my noviceness):
The PHP form is being executed. ReceiveLoginData function prints ["noemail"] whenever the submit button is pressed
The Network debugging tab in chrome's dev tools shows that connection is established with php file.
Some information which might just be useful:
Response Headers (source):
HTTP/1.1 200 OK
Host: localhost:4000
Date: Sun, 18 Sep 2022 16:59:49 GMT
Connection: close
X-Powered-By: PHP/8.1.10
Content-type: text/html; charset=UTF-8
Request Headers (source):
POST /users/auth/login.php HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: keep-alive
Content-Length: 31
Content-type: application/x-www-form-urlencoded
Host: localhost:4000
Origin: http://localhost:4000
Referer: http://localhost:4000/users/auth/auth.html?
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36
sec-ch-ua: "Google Chrome";v="105", "Not)A;Brand";v="8", "Chromium";v="105"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Linux"
Payload: (source | URL encoded)
uemail=email%40gmail.com&upasswd=1234
uemail: email%40gmail.com
upasswd: 1234
Response:
"[\u0022noemail\u0022]"
What else I did...
I didn't waste those 5 hours on this project...
I tried to remake a smaller project with the same mechanism and the same js code calling a PHP file and voila, the php file got the values posted to it...
Everything "seems" correct according to my knowledge but why does PHP not get the $_POST values?
Also, I'm currently focusing on Google Chrome and am on Linux (ig that makes no difference...)
From the code you have posted i can spot one problem.
the $uemail = $_POST["uemail"]; is in the global scope and the code inside the main_fn function is trying to use that variable but that variable is not available in that scope because it is only available in the global scope. So it seems to me you need to pass them as arguments to get them into the functions scope.
Changeing the function definition
from: function main_fn()
to: function main_fn($uemail, $upasswd)
and calling it
with: main_fn($uemail, $upasswd);
instead of: main_fn();
should do the trick
Hope this helps :-)
Trying to make a call and retrieve a very simple, one line, JSON file.
$(document).ready(function() {
jQuery.ajax({
type: 'GET',
url: 'http://wncrunners.com/admin/colors.json' ,
dataType: 'jsonp',
success: function(data) {
alert('success');
}
});
});//end document.ready
Here's the RAW Request:
GET http://wncrunners.com/admin/colors.json?callback=jQuery16406345664265099913_1319854793396&_=1319854793399 HTTP/1.1
Host: wncrunners.com
Connection: keep-alive
Cache-Control: max-age=0
User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.106 Safari/535.2
Accept: */*
Referer: http://localhost:8888/jquery/Test.html
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Here's the RAW Response:
HTTP/1.1 200 OK
Date: Sat, 29 Oct 2011 02:21:24 GMT
Server: Apache/1.3.33 (Unix) mod_ssl/2.8.22 OpenSSL/0.9.7d SE/0.5.3
Last-Modified: Fri, 28 Oct 2011 17:48:47 GMT
ETag: "166a2402-10-4eaaeaff"
Accept-Ranges: bytes
Content-Length: 16
Content-Type: text/plain
Connection: close
{"red" : "#f00"}
The JSON is coming back in the response (red : #f00), but Chrome reports Uncaught SyntaxError: Unexpected token : colors.json:1
If I navigate directly to url itself, the JSON is returned and is displayed in the browser.
If I paste the contents of colors.json into JSLINT, the json validates.
Any ideas why I can't get this error and I never make it to the success callback?
EDIT - the jQuery.ajax() call above runs perfect at jsfiddle.net, and returns the alert 'success' as expected.
EDIT 2 - this URL works fine 'http://api.wunderground.com/api/8ac447ee36aa2505/geolookup/conditions/q/IA/Cedar_Rapids.json' I noticed that it returned as TYPE: text/javascript and Chrome did not throw the Unexpected Token. I've tested several other url's and the ONLY one that does not throw the Unexptected Token is the wunderground that is returned as TYPE: text/javascript.
Streams returned as text/plain and application/json are not being parsed correctly.
You've told jQuery to expect a JSONP response, which is why jQuery has added the callback=jQuery16406345664265099913_1319854793396&_=1319854793399 part to the URL (you can see this in your dump of the request).
What you're returning is JSON, not JSONP. Your response looks like
{"red" : "#f00"}
and jQuery is expecting something like this:
jQuery16406345664265099913_1319854793396({"red" : "#f00"})
If you actually need to use JSONP to get around the same origin policy, then the server serving colors.json needs to be able to actually return a JSONP response.
If the same origin policy isn't an issue for your application, then you just need to fix the dataType in your jQuery.ajax call to be json instead of jsonp.
I have spent the last few days trying to figure this out myself. Using the old json dataType gives you cross origin problems, while setting the dataType to jsonp makes the data "unreadable" as explained above. So there are apparently two ways out, the first hasn't worked for me but seems like a potential solution and that I might be doing something wrong. This is explained here [ https://learn.jquery.com/ajax/working-with-jsonp/ ].
The one that worked for me is as follows:
1- download the ajax cross origin plug in [ http://www.ajax-cross-origin.com/ ].
2- add a script link to it just below the normal jQuery link.
3- add the line "crossOrigin: true," to your ajax function.
Good to go! here is my working code for this:
$.ajax({
crossOrigin: true,
url : "https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=-33.86,151.195&radius=5000&type=ATM&keyword=ATM&key=MyKey",
type : "GET",
success:function(data){
console.log(data);
}
})
I had the same problem and the solution was to encapsulate the json inside this function
jsonp(
.... your json ...
)
That hex might need to be wrapped in quotes and made into a string. Javascript might not like the # character
response is JSON
Edge: sometimes inserts response property value into DOM briefly then removes it, sometimes logs error "SCRIPT5: access denied" (indicating CORS), response fully accessible from Debugger, request shown in network tab
Chrome: response empty string, request not shown in network tab, no console message
Firefox: console error 'response "malformed JSON"' on breakpoint line using response in JSON.parse(), thus before usage, request not shown in network tab, Firebug and integrated
JS (current browsers only):
var session = "";
var request;
function checkLogin()
{
if(request.readyState > 3)
{
var response = JSON.parse(request.response);
if(verify(response)) // verify inserts argument property "error" in DOM on error via innerHTML on element
{
// do something
}
}
}
function login()
{
request = new XMLHttpRequest();
request.onreadystatechange = checkLogin;
request.open("GET", "authenticateUser.php?user=" + document.getElementById("user").value + "&credential="+md5(document.getElementById("password").value));
request.send();
}
Edge request from network tab:
Anforderungs-URL: http://*MYDOMAIN*/authenticateUser.php?user=df&credential=d41d8cd98f00b204e9800998ecf8427e
Anforderungsmethode: GET
Statuscode: 200 / OK
- Anforderungsheader
Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: de-DE, de; q=0.8, en-US; q=0.5, en; q=0.3
Connection: Keep-Alive
Host: *MYDOMAIN*
Referer: http://*MYDOMAIN*/
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Safari/537.36 Edge/13.10586
- Antwortheader
Connection: Keep-Alive
Content-Length: 65
Content-Type: application/json
Date: Sat, 21 Nov 2015 07:42:17 GMT
Keep-Alive: timeout=15, max=94
Server: Apache
X-Powered-By: PHP/5.5.29
response:
{"success":false,"error":"authentication failed or unauthorised"}
What is going to make my phps' response be usable in JS code (in Chrome and Firefox) and its properties value be insertable into the DOM?
login() is the handler of onsubmit. I didn't return false; thus the form from which the user and pw came from - having no action - submitted to its own page and made the browser reload the page: cancelling the request in Chrome and Ff. Only Edge let the equal page JS handle the repsonse from the former loads request - until it was to be inserted.
Took me 6 hours and a detour through JSONP and Charles then listing the network traffic from Chrome where the page itself appeared after the request thus letting me have the idea that the page "reloaded" and finally remembering onsubmits handler cancels the submit with return false and else submits leading to a load of the action (or self if none) which is what happened here.
I am using the Framey API for video recording. When I make a request I get back the json response I expect, but an error is raised:
Uncaught SyntaxError: Unexpected token :
Here's the javascript
var url = "http://framey.com/api/videos/ba9bd910-549d-012e-32f4-549a20bdfc52?
api_key=7VNKGLJZLKSASZ0FXN2TVSZQU&signature=41B08D68E0A4AC2DD91107BBD6AD08B8&time_stamp=1304447242";
$("button").click(function() {
$.ajax({
url: url,
dataType: 'json',
crossDomain: true
}).done(function() {
$(".video").html("here it is babyF!");
});
});
The url is just an example url from Framey's website, I don't know if it works. From reading this question Uncaught SyntaxError: Unexpected token :, I think that I maybe having the same problem. The selected answer to that question is
Just an FYI for people who might have the same problem -- I just had
to make my server send back the JSON as application/json and the
default jQuery handler worked fine.
I don't think I can effect the way Framey is sending me back the data, so I'm not sure how to fix this. Maybe it is something else all together? Thanks in advance and let me know if you need more information.
=========EDIT============
Here is the response from Framey that is giving me the error:
{"success":true,"video":{"name":"6d235a90-7b4b-012f-f97e-12313d297e67","filesize":1335504,"duration":20.48,"state":"uploaded","views":1,"data":{},"flv_url":"http://framey.com/videos/source/6d235a90-7b4b-012f-f97e-12313d297e67.flv","mp4_url":"http://framey.com/videos/source/6d235a90-7b4b-012f-f97e-12313d297e67.mp4","large_thumbnail_url":"http://framey.com/thumbnails/large/6d235a90-7b4b-012f-f97e-12313d297e67.jpg","medium_thumbnail_url":"http://framey.com/thumbnails/medium/6d235a90-7b4b-012f-f97e-12313d297e67.jpg","small_thumbnail_url":"http://framey.com/thumbnails/small/6d235a90-7b4b-012f-f97e-12313d297e67.jpg"}}
I think it is something about Framey putting "application/javascript" in the place where it should be saying "application/json"
============ EDIT 2 =================
Here are the headers for the response, I got these by looking at the "Network" section of the console in Chrome.
Request URL:http://www.framey.com/api/videos/32a7aaf0-7c3a-012f-37bd-12313b093125?api_key=00000000&signature=624643a3481b2a2c2bdb6c7cc29c506e&time_stamp=1536494436&callback=jQuery17202607689620926976_1336594235235&_=1336594483714
Request Method:GET
Status Code:200 OK
Request Headersview source
Accept:*/*
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Cookie:__utma=229279307.404664337.1336485291.1336573199.1336589854.6; __utmc=229279307; __utmz=229279307.1336485291.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); _video-recorder_session=BAh7B0kiD3Nlc3Npb25faWQGOgZFRiIlN2VjODBiYWM1NDk2MDlkYTg2ZTY0NzEzNDA5Zjg3ZGJJIhBfY3NyZl90b2tlbgY7AEZJIjE4aW5KVktxakhyVTRvVGY0RXZlNkVkMU9lV0p1NUEzR01rVzlNK1hRWEJ3PQY7AEY%3D--b9a5f6cf08d7539d2bf9ebebc83ce96b0d070615
Host:www.framey.com
Referer:http://localhost:3000/questions/1
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.168 Safari/535.19
Query String Parametersview URL encoded
api_key:000000000000
signature:624643a3481b2a2c2bdb6c7cc29c506e
time_stamp:1536494436
callback:jQuery17202607689620926976_1336594235235
_:1336594483714
Response Headersview source
Cache-Control:max-age=0, private, must-revalidate
Connection:keep-alive
Content-Length:709
Content-Type:text/javascript; charset=utf-8
ETag:"5e8393861da01fa2effd911365a90e6b"
Server:nginx/1.0.10 + Phusion Passenger 3.0.11 (mod_rails/mod_rack)
Set-Cookie:_video-recorder_session=BAh7B0kiD3Nlc3Npb25faWQGOgZFRiIlN2VjODBiYWM1NDk2MDlkYTg2ZTY0NzEzNDA5Zjg3ZGJJIhBfY3NyZl90b2tlbgY7AEZJIjE4aW5KVktxakhyVTRvVGY0RXZlNkVkMU9lV0p1NUEzR01rVzlNK1hRWEJ3PQY7AEY%3D--b9a5f6cf08d7539d2bf9ebebc83ce96b0d070615; path=/; HttpOnly
Status:200
X-Powered-By:Phusion Passenger (mod_rails/mod_rack) 3.0.11
X-Runtime:0.060476
X-UA-Compatible:IE=Edge,chrome=1
Of particular interest is the content-type header: it is text/javascript.
Where did you find that demo code (I could not find it on the Framey site)? I suspect you will run into cross-domain issues trying to use the Framey REST API from the client. Is your code on a publicly accessible server somewhere that we can take a look?
I am trying to build Multipart Form Data directly in Javascript in order to send my data to a server. I know there are Ajax form plugins, but I really think they wont suit my needs as I will create binary data in the browser and send it as if it were a file submit (The server I will post to requires it that way).
My problem now is that the simplest example of building text Multipart MIME data fails on the server side with an error:
500 Internal Server Error: Invalid boundary in multipart form
I have tried to reduce the code to a bare minimum: In this main.html (this is the name it will be refered to later in the server code) , there are both an html form to submit text the html-non-Ajax way and also a Javascript function which tries to replicate that with XmlHttprequest:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Posting MIME Multipart directly in Javascript</title>
<script>
function sendMimeMultipart(url, data) {
boundary = '---------------------------1504702169761927311267328916'
xhr = new XMLHttpRequest();
xhr.open("POST", url);
//Build the MIME POST request.
var body = "--" + boundary + "\r\n";
body += 'Content-Disposition: form-data; name="contents"\r\n\r\n';
body += data+"\r\n";
body += "--" + boundary + "--"+"\r\n";
var fileSize = body.length
xhr.setRequestHeader("Content-Type", "multipart/form-data, boundary="+boundary);
xhr.setRequestHeader("Content-Length", fileSize);
xhr.send(body);
return true;
}
function sendData() {
sendMimeMultipart('http://localhost:8080/myhandler', "Hello World!");
}
</script>
</head>
<body onload='sendData()'>
<form action = "myhandler" method = "post" enctype = "multipart/form-data">
<input type = "text" name = "contents">
<input type = "submit">
</form>
</body>
</html>
This is the Request object that arrives to the server when using the form:
Request: POST /myhandler
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Accept-Language: es-es,es;q=0.8,en-us;q=0.5,en;q=0.3
Connection: keep-alive
Content-Length: 187
Content-Type: multipart/form-data;
boundary=---------------------------18171295601131570933197493099
Host: localhost:8080
Keep-Alive: 115
Referer: http://localhost:8080/
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; es-ES; rv:1.9.2.20)
Gecko/20110803 Firefox/3.6.20
-----------------------------18171295601131570933197493099
Content-Disposition: form-data; name="contents"
Hello World!
-----------------------------18171295601131570933197493099--
And this the Request object arriving to the server when using the Javascript function (sendMimeMultipart):
Request: POST /myhandler
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Accept-Language: es-es,es;q=0.8,en-us;q=0.5,en;q=0.3
Cache-Control: no-cache
Connection: keep-alive
Content-Length: 185
Content-Type: multipart/form-data; charset=UTF-8,
boundary=---------------------------1504702169761927311267328916
Host: localhost:8080
Keep-Alive: 115
Pragma: no-cache
Referer: http://localhost:8080/
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; es-ES; rv:1.9.2.20)
Gecko/20110803 Firefox/3.6.20
-----------------------------1504702169761927311267328916
Content-Disposition: form-data; name="contents"
Hello World!
-----------------------------1504702169761927311267328916--
The difference of 2 bytes in Content-Length is because the browser generates the boundaries randomly, being sometimes longer and sometimes shorter. In this case it is one character longer, what accounts for the two byte difference in the two boundary occurrences.
I dont think the server has much to do with this, bus just in case I post the server side code. It is an Appengine snippet intended only for localhost usage; the call to "localhost:8080/myhandler" retrieves the value of "contents" posted by the browser and stores it in a global variable. After that, a call to "localhost:8080/show" displays the text previously retrieved. As I mentioned before, if we send the data using the form, the text content is correctly saved and the "show" handler displays it. If however we use the Javascript, the line of code:
contents = self.request.get("contents")
In MyHandler (code below), produces the error.
Here is the server code:
import cgi
import datetime
import logging
import os
from google.appengine.ext import db
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.api import images
from google.appengine.ext.webapp import template
from os import environ
contents=''
class mein(webapp.RequestHandler):
def get(self):
template_values = {}
path = os.path.join(os.path.dirname(__file__), 'templates/main.html')
self.response.out.write(template.render(path, template_values))
class MyHandler(webapp.RequestHandler):
def post(self):
global contents
contents = self.request.get("contents")
class Show(webapp.RequestHandler):
def get(self):
global contents
self.response.headers['Content-Type'] = "text/plain"
self.response.out.write(contents)
application = webapp.WSGIApplication([
('/', mein),
('/myhandler', MyHandler),
('/show', Show)
], debug=True)
def main():
run_wsgi_app(application)
if __name__ == '__main__':
main()
Any idea of why this should be failing? I have tried a zillion different things, but I dont seem to be able to make it work or to understand the reason why it doesnt!.
Thanks very much in advance for your ideas and help.
All the best:
-Javier
I encountered the same error message when trying to construct a http file upload manually. I got it to work by replacing the comma(,) with a semicolon(;) in the Content-Type headers. In your case, by replacing:
xhr.setRequestHeader("Content-Type", "multipart/form-data, boundary="+boundary);
with:
xhr.setRequestHeader("Content-Type", "multipart/form-data; boundary="+boundary);
This seems to be related to the Python backend, because I had this same problem with Django(Python) and when I debugged it against a PHP test server both comma and semicolon worked.
Finally, the example in RFC1867 DO use a comma so in the end I'm unsure what really is the correct way to do it, but semicolon solved it for me.