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');
Related
I am making a GET request to the api using XMLHttpRequests. The api takes in a "uuid" value denoted by the variable "a" here as a parameter, uses that value for processing and is supposed to spit out some information that I am trying to print to the console.
However, the problem I am running into is that, whenever the api successfully receives the uuid value it returns a message where the newresponse.response.status is Initiated. However I want to wait till the newresponse.response.status is Success (this usually takes a short bit like 3-4 seconds more).
The original code is shown below:
function getrequestresults(status, response) {
let parse = JSON.parse(response);
let a = parse.uuid;
let newrequest = new XMLHttpRequest();
newrequest.open('GET', "http://localhost:5000/api/v1/dags/results" + "?" + "uuid" + "=" + a, true);
newrequest.onload = function() {
//console.log(newrequest.status);
console.log(newrequest.response);
};
newrequest.send();
}
One of the attempts I made at fixing this was as follows:
function getrequestresults(status, response) {
let parse = JSON.parse(response);
let a = parse.uuid;
let newrequest = new XMLHttpRequest();
newrequest.open('GET', "http://localhost:5000/api/v1/dags/results" + "?" + "uuid" + "=" + a, true);
newrequest.onload = function() {
while (newrequest.response.status != "Success") {
//the following line was just to see what's going on, idea was to keep looping till, desired status is reached
console.log(newrequest.response);
}
//console.log(newrequest.status);
console.log(newrequest.response);
};
newrequest.send();
}
However, this did not work as it seems that the "onload" function only runs once, whereas I need it to run multiple times until newrequest.response.status is Success.
I am quite new with sending XMLHttpRequests and some help would be appreciated. Thanks.
We want to send a boolean value from python to javascript so we can use it in our html website.
We tried using sockets but thats too complicated for us. Our next thought was to use an api and we know how to get information from an api using javascript. What we want to do is post a python boolean value to an api, and then get the boolean value from the api using javascript.
But we don't know how to do so.
We are using a raspberry pi for all our code and a hardware-button which returns true in python when pressed.
We are currently testing code we found from https://healeycodes.com/javascript/python/beginners/webdev/2019/04/11/talking-between-languages.html
But this code doesnt work for us.
We are also using pycharm as our workspace, is this a problem?
Our current code in javascript:
const request = new XMLHttpRequest();
request.open("GET", url, true);
request.onreadystatechange = function() {
if (request.readyState === 4 && request.status === 200) {
success(JSON.parse(request.responseText));
}
};
request.send();
setInterval(get("button-status.json", receiveStatus), 3000);
}
function receiveStatus(response) {
if (response.status !== status) { // only do something if status has changed
status = response.status;
console.log('button status is now', status);
}
}
let status;
// checks every 100ms
get()
Our python code we're using for testing:
import random
import json
import time
button_status = False
path = (r"C:\Users\Sam\Desktop\pythonProject\pythonflask\emplates") # replace with your actual path
def save_button_status():
with open(path + "/button-status.json", "w") as f:
json.dump({'status': button_status}, f)
while True :
value = random.randrange(1, 10)
if ( value <= 5) :
button_status = True
save_button_status()
time.sleep(3)
else :
button_status = False
save_button_status()
time.sleep(3)
print(button_status)
Javascript within a webpage cannot directly run a Python script on your computer or read information from a local terminal. What you could do is have your Python program output a small json file to your localhost folder which is overwritten when the button is pressed or released, like this:
import json
button_status = False # assuming it is initially off
path = "path/to/your/localhost/folder" # replace with your actual path
def save_button_status():
with open(path + "/button-status.json", "w") as f:
json.dump({'status': button_status}, f)
# Then call save_button_status() whenever the status changes
Then in your javascript, set an interval to periodically call a function that gets this json file and does something based on the value if it has changed:
function get(url, success) {
//--- Get JSON data at the given URL and call `success` if successful
const request = new XMLHttpRequest();
request.open("GET", url, true);
request.onreadystatechange = function() {
if (request.readyState === 4 && request.status === 200) {
success(JSON.parse(request.responseText));
}
};
request.send();
}
function receiveStatus(response) {
if (response.status !== status) { // only do something if status has changed
status = response.status;
console.log('button status is now', status);
}
}
let status;
let interval = setInterval(() => get("button-status.json", receiveStatus), 100); // checks every 100ms
There may be some lag as your local server updates the file.
You can try to set up a SQL Database. Write a SQL statement in Python to receive your boolean. After that make a PHP script on your Web server to receive the SQL data. Then sent a request to the URL of the PHP script using an XHTTP JavasScript request.
I'm trying to create a Shared Access Signature client side in my Node app. The reason being that I do not want to stream files through my app. I want the user to be able to upload a file to my Azure Data Lake Gen2 Blob Storage container directly.
I have looked at all examples I can find, but they are all server side. So I tried to generate generateDataLakeSASQueryParameters and use them in the PUT request. The process looks like it works and I return it to the client.
Server side:
async getFileUploadUrl(path) {
const now = new Date().toUTCString();
const startsOn = new Date(now);
startsOn.setMinutes(startsOn.getMinutes() - 10); // Skip clock skew with server
const expiresOn = new Date(now);
expiresOn.setHours(expiresOn.getHours() + 1); // Expires in one hour
const sharedKeyCredential = new StorageSharedKeyCredential(this.storageAccountName, this.accountKey);
const sas = generateDataLakeSASQueryParameters({
fileSystemName: this.fileSystemClient.name,
ipRange: { start: "0.0.0.0", end: "255.255.255.255" },
expiresOn,
protocol: SASProtocol.HttpsAndHttp,
permissions: DataLakeSASPermissions.parse("c").toString(), // Read (r), Write (w), Delete (d), List (l), Add (a), Create (c), Update (u), Process (p)
resourceTypes: AccountSASResourceTypes.parse("o").toString(), // Service (s), Container (c), Object (o)
services: AccountSASServices.parse("b").toString(), // Blob (b), Table (t), Queue (q), File (f)
startsOn,
version: "2019-12-12"
},
sharedKeyCredential);
const encodedURI = encodeURI(path);
const filePath = `${this.fileSystemClient.url}/${encodedURI}`;
return {
url: filePath,
signature: sas.signature,
};
}
Client side:
const { url, signature } = serverResponse;
const file = [file takes from an input tag];
const request = new XMLHttpRequest();
request.open('PUT', url, true);
request.setRequestHeader("x-ms-date", new Date().toUTCString());
request.setRequestHeader("x-ms-version", '2019-12-12');
request.setRequestHeader("x-ms-blob-type", 'BlockBlob');
request.setRequestHeader("Authorization", `SharedKey [storageaccount]:${signature}`);
request.send(file);
And what I keep getting back is a 403 with the following error:
The MAC signature found in the HTTP request '[signature]' is not the
same as any computed signature. Server used following string to sign:
'PUT\n\n\n1762213\n\nimage/png\n\n\n\n\n\n\nx-ms-date:Thu, 24 Sep 2020
12:24:05 GMT\nx-ms-version:2019-12-12\n/[account name]/[container
name]/[folder name]/image.png'.
Obviously I removed the actual signature since I have gotten it to work server side, but it looks something like this: hGhg765+NIGjhgluhuUYG686dnH90HKYFytf6= (I made this up, but it looks as if it's in the correct format).
I have also tried to return the parsed query string and used in a PUT request, but then I get errors stating there is a required header missing, and I cannot figure out which one that should be. No Authorization for instance should be required.
The method generateDataLakeSASQueryParameters is used to create a service sas token. After doing that, we can call Azure Datalake Rest API with the sas token as the query paramater
For example
Create sas token with method generateDataLakeSASQueryParameters. When we call method generateDataLakeSASQueryParameters, we should define a DataLakeSASSignatureValues class : https://learn.microsoft.com/en-us/javascript/api/#azure/storage-file-datalake/datalakesassignaturevalues?view=azure-node-latest
const {
StorageSharedKeyCredential,
generateDataLakeSASQueryParameters,
DataLakeSASPermissions,
} = require("#azure/storage-file-datalake");
const accountName = "testadls05";
const accountKey ="";
const now = new Date().toUTCString();
const startsOn = new Date(now);
startsOn.setMinutes(startsOn.getMinutes() - 10); // Skip clock skew with server
const expiresOn = new Date(now);
expiresOn.setHours(expiresOn.getHours() + 1); // Expires in one hour
const fileSas = generateDataLakeSASQueryParameters(
{
fileSystemName: "test",
pathName: "test.jpg",
permissions: DataLakeSASPermissions.parse("racwd"),
startsOn: startsOn,
expiresOn: expiresOn,
},
new StorageSharedKeyCredential(accountName, accountKey)
).toString();
console.log(fileSas);
Test (create file)
PUT http:// https://{accountName}.{dnsSuffix}/{filesystem}/{path}
?{sas token you create in step1}
Headers:
Content-Type:image/jpeg
Content-Length:0
This question already has answers here:
How to replace the entire html webpage with ajax response?
(6 answers)
How to replace innerHTML of a div using jQuery?
(14 answers)
Closed 3 years ago.
In index.html, I'm getting a value stored in localStorage:
<script>
function checkChannel() {
if (localStorage.getItem('channel')) {
const channel = localStorage.getItem('channel');
const request = new XMLHttpRequest();
request.open('POST', '/convert');
// Add data to send with request
const data = new FormData();
data.append('channel', channel);
// Send request
request.send(data);
}
}
</script>
</head>
<body onload="checkChannel()">
.
.
.
This works fine. It is routed to the code below in application.py. The debugger hits the first line in convert() below, so I know it's getting there.
#app.route("/convert", methods=["POST"])
def convert():
channel = request.form.get("channel")
channel_messages = channels_dict[channel]
return render_template("channel.html", channel=channel, channel_messages=channel_messages)
However, channel.html is not being rendered. Instead, it stays on the same page. What am I doing wrong here? I can give more details if needed.
You need to define a request.onload() function. This function will be called after the response is received. so your JS code will be similar to this:
function checkChannel() {
if (localStorage.getItem('channel')) {
const channel = localStorage.getItem('channel');
const request = new XMLHttpRequest();
request.open('POST', '/convert');
// Add data to send with request
const data = new FormData();
data.append('channel', channel);
// Send request
request.send(data);
// 4. This will be called after the response is received
request.onload = function() {
if (request.status != 200) {
// analyze HTTP status of the response
alert(`Error ${request.status}: ${request.statusText}`);
// e.g. 404: Not Found
} else { // show the result
$('body').html(request.response)
}
};
}
}
Please note that you can replace $('body').html('some content') by $('div').html('some content') or $('#some-id').html('some content') based on channel.html file content.
Please find this example.
I am currently trying to write some Javascript to interact with an API that I deployed on GAE (using Python) using XMXMLHttpRequest(). I've had no issue getting a GET, however the PUT is giving me a lot of trouble.
Interestingly, I have no issue touching the PUT request from a test HTTP site (https://www.hurl.it/), however I receive a status value of 0 every time I try from my own Javascript code. Below are snippets of my GAE and Javascript code.
(NOTE - I must use a "put" for this call as a requirement.)
Any guidance would be appreciated!
GAE (Server):
def put(self):
# Save variables for update
cardkey = self.request.get('key', default_value=None)
ident = self.request.get('ident', default_value=None)
brand = self.request.get('brand', default_value=None)
year = self.request.get('year', default_value=None)
player = self.request.get('player', default_value=None)
# If card key is provided then update card
if cardkey:
# Get card
card_to_update = ndb.Key(db_models.Card, int(cardkey)).get()
if ident:
card_to_update.ident = ident
if brand:
card_to_update.brand = brand
if year:
card_to_update.year = year
if player:
card_to_update.player = player
# Save changes and print update to requester
card_to_update.put()
card_dict_format = card_to_update.to_dict()
self.response.write(json.dumps(card_dict_format))
return
# If card key is not provided send error
else:
self.response.write('key not provided. must provide key for update.')
return
And the Javascript from my webpage:
<script>
window.onload = function()
{
var myRequest = new XMLHttpRequest();
var url = 'http://cs496-assignment3-mastrokn.appspot.com/updatecard';
var param = 'key=5636318331666432';
myRequest.open('put', url);
myRequest.onreadystatechange = function()
{
if ((myRequest.readyState == 4) && (myRequest.status == 200))
{
// var myArr = JSON.parse(myRequst.responseText);
// myFunction(myArr);
document.getElementById("viewCards").innerHTML = myRequest.status;
}
else
{
document.getElementById("viewCards").innerHTML = myRequest.status;
}
}
myRequest.send(param);
}
</script>
First, your onreadystatechange() handler should look like this:
myRequest.onreadystatechange = function()
{
if (myRequest.readyState == 4) //Don't do anything until the readyState==4
{
if(myRequest.status == 200) //Check for status==200
{
document.getElementById("viewCards").innerHTML = myRequest.status;
}
else //All other status codes
{
document.getElementById("viewCards").innerHTML =
'readyState='
+ myRequest.readyState
+ ' status='
+ myRequest.status
+ ' status text='
+ myRequest.statusText;
}
}
}
Then, from the docs:
If you end up with an XMLHttpRequest having status=0 and
statusText=null, it means that the request was not allowed to be
performed. It was UNSENT.
To see what went wrong, check the javascript console in your browser for an error, e.g.:
[Error] XMLHttpRequest cannot load
http://cs496-assignment3-mastrokn.appspot.com/updatecard. Origin
http://localhost:4567 is not allowed by Access-Control-Allow-Origin.
(4.htm, line 0)
When I run the code above and send the XMLHttpRequest to my own local server, the PUT request succeeds with a status code of 200.
Lastly, I have doubts about the server code you posted because I don't know of any framework where you return None from a request handler--rather you return some string or a response object. Yet, using other means to make a PUT request to your url returns a 200 status code. Is that really your server code? What framework are you using?