Javascript - POST request from server/back-end doesn't work - javascript

I am using an API for text-translatation ( you can find it here: Yandex ).
The following piece of code is in the front-end and works fine:
var url = "https://translate.yandex.net/api/v1.5/tr.json/translate",
keyAPI = "myKey/hidden";
var xhr = new XMLHttpRequest(),
textAPI = "fa asta sa fie in engleza";
langAPI = "en";
data = "key="+keyAPI+"&text="+textAPI+"&lang="+langAPI;
xhr.open("POST",url,true);
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xhr.send(data);
xhr.onreadystatechange = function() {
if (this.readyState === 4 && this.status === 200) {
var res = this.responseText;
var json = JSON.parse(res);
if (json.code === 200) {
console.log( json.text[0]);
}
else {
console.log("Error Code: " + json.code);
}
}
};
The console in the browser outputs:
do this to be in English
So it's fine.
However, I need to do this in the back-end. So, I know that XMLHttpRequest is built-in browser, but not in node, therefore I installed it using: npm install xmlhttprequest and I tried to use the same code as I used in the front-end, but I added a log on xhr.onreadystatechange to tell me the status:
xhr.onreadystatechange = function() {
console.log(this.status);
if (this.readyState === 4 && this.status === 200) {
var res = this.responseText;
var json = JSON.parse(res);
if (json.code === 200) {
console.log( json.text[0]);
}
else {
console.log("Error Code: " + json.code);
}
}
};
And what I get is:
0
and
415
As the status.
So it didn't work. I decided to use request instead:
var url = "https://translate.yandex.net/api/v1.5/tr.json/translate";
var keyAPI = "hidden;
var xhr = new XMLHttpRequest();
var textAPI = "fa asta sa fie in engleza";
var langAPI = "en";
request.post({
url: url,
body: JSON.stringify({
key : keyAPI,
text: "tradu",
lang : langAPI
}),
json: true
}, function(err, response, body) {
if(err) {
console.log(err);
return;
}
console.log(body);
});
And the output I get is :
{ code: 415, message: 'Unsupported media type' }
So again, it doesn't work. I also tried adding headers in the post requests, like this:
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
But it made no difference.
I did some digging and found out that status 415 means Unsupported Media Type and I also read some posts/fixes about this but none helped me.

To get it to work, use the form key to send your data (using request)
var url = "https://translate.yandex.net/api/v1.5/tr.json/translate";
var keyAPI = "hidden";
var textAPI = "fa asta sa fie in engleza";
var langAPI = "en";
request.post({
url: url,
form: {
text: textAPI,
key: keyAPI,
lang: langAPI
},
}, function(err, response, body) {
if(err) {
console.log(err);
return;
}
console.log(body);
});

Related

Jquery REST API POST call, I'm getting 415 error?

I'm trying to translate one of my powershell scripts which makes an API call, into javascript or jquery for a chrome extension. I'm not very versed in Jquery, so I'm getting an error 415 when making a call with the below code, unsupported media type. I think I have to tell it I'm using "Content-Type","application/json"... but I'm not doing this in my powershell script untile subsequent calls after I've already gotten my token, so I'm a little confused. Why am I getting a 415 error and how do I fix it?
var token
var userName = "userID";
var passWord = "PaSSwOrD";
var tokenURL = "https://55.55.55.55/api/v1/token";
var xhr = new XMLHttpRequest();
var data =
'&grant_type=password';
'&server_host=55.55.55.55' +
'&username=' + userName +
'&password=' + passWord;
var dataFinal = encodeURI(data);
xhr.open('POST', tokenURL, true);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
//do something
}
}
xhr.send(data);
alert(xhr.responseText);
Try this (if we talk about jQuery):
var obj = null
$.ajax({
url: "https://55.55.55.55/api/v1/token",
method: 'POST',
async: false,
data: {
grant_type: 'password',
server_host: '55.55.55.55',
username: 'userID',
password: 'PaSSwOrD'
},
headers: {
'Content-type': 'application/x-www-form-urlencoded',
Accept:'application/json'
},
success: function(data){
obj = data // here the result
}
})
console.log(obj) // here the result because of "async: false"

404 on large file uploads using google drive api

I am trying to upload files to Google Drive via their api. When the file is over roughly 60MB it seems to be giving me a 404 or something went wrong screen.
I've tried several methods and noticed in 2015 alot of people were having similar issues because Google did not support resumable uploads from browser. I don't know if this has changed or not, but it seems to work fine for files under 60MB.
//const file = new File(['Hello, world!'], 'hello world.txt', { type: 'text/plain;charset=utf-8' });
const contentType = file.type || 'application/octet-stream';
const user = gapi.auth2.getAuthInstance().currentUser.get();
const oauthToken = user.getAuthResponse().access_token;
const initResumable = new XMLHttpRequest();
initResumable.open('POST', 'https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable', true);
initResumable.setRequestHeader('Authorization', 'Bearer ' + oauthToken);
initResumable.setRequestHeader('Content-Type', 'application/json');
initResumable.setRequestHeader('X-Upload-Content-Length', file.size);
initResumable.setRequestHeader('X-Upload-Content-Type', contentType);
initResumable.onreadystatechange = function () {
if (initResumable.readyState === XMLHttpRequest.DONE && initResumable.status === 200) {
const locationUrl = initResumable.getResponseHeader('Location');
const reader = new FileReader();
reader.onload = (e) => {
const uploadResumable = new XMLHttpRequest();
uploadResumable.open('PUT', locationUrl, true);
uploadResumable.setRequestHeader('Content-Type', contentType);
uploadResumable.setRequestHeader('X-Upload-Content-Type', contentType);
uploadResumable.onreadystatechange = function () {
if (uploadResumable.readyState === XMLHttpRequest.DONE && uploadResumable.status === 200) {
console.log(uploadResumable.response);
}
};
uploadResumable.send(reader.result);
};
reader.readAsArrayBuffer(file);
}
};
// You need to stringify the request body containing any file metadata
initResumable.send(JSON.stringify({
'name': file.name,
'mimeType': contentType,
'Content-Type': contentType,
'Content-Length': file.size
}));

Making synchoronous XHR request with chrome.webRequest.onBeforeRequest

I'm looking to make a Chrome extension that hooks in to chrome.webRequest.onBeforeRequest to determine whether or not to block the current page request. As a result, I need to make a request to an API to determine it.
Is there a good way to make the checkUrl request synchronous to satisfy the requirements of chrome.webRequest.onBeforeRequest?
function checkUrl(url, callback) {
let api = 'http://localhost:9000/filter';
let data = {
url: url,
};
let json = JSON.stringify(data);
let xhr = new XMLHttpRequest();
xhr.open('POST', api, true);
xhr.setRequestHeader('Content-Type', 'application/json;charset=UTF-8');
xhr.setRequestHeader('X-Bark-Email', email);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
callback(xhr.response);
}
}
xhr.send(json);
}
function onBeforeRequestHandler(details) {
let url = new URL(details.url);
console.log(details.type, ": ", url.host)
checkUrl(url, function(resp) {
let status = resp.status;
let redirectUrl = resp.redirect_url;
if (status == "allowed") {
return { cancel: false }; // <<<<< This doesn't work b/c of the callback
} else {
return { redirectUrl: redirectUrl };
}
});
}
chrome.webRequest.onBeforeRequest.addListener(onBeforeRequestHandler,
{
urls: ["<all_urls>"],
types: ["sub_frame", "main_frame", "xmlhttprequest"]
},
["blocking"]
);
I swapped:
xhr.open('POST', api, true);
for
xhr.open('POST', api, false);
and that makes the request synchronous. Then returned the result from the xhr request and use that inline:
return JSON.parse(xhr.response);

How to convert this JS code to use in Nodejs api?

I want use my api to send e-mail in some cases,the service (infobip) docs show an example in JS but it don't work in my api with nodejs and expressjs. Can someone help me?
/*----Sending fully featured email----*/
function createFormData(data) {
var formData = new FormData();
for (var key in data) {
formData.append(key, data[key]);
}
return formData;
}
//Dummy File Object
var file = new File([""], "filename");
var data = {
'from': 'Sender Name <from#example.com>',
'to': 'recipient1#example.com',
'subject': 'Test Subject',
'html': '<h1>Html body</h1><p>Rich HTML message body.</p>',
'text': 'Sample Email Body',
'attachment': file,
'intermediateReport': 'true',
'notifyUrl': 'https://www.example.com/email/advanced'
};
var xhr = new XMLHttpRequest();
xhr.withCredentials = false;
xhr.addEventListener('readystatechange', function () {
if (this.readyState === this.DONE) {
console.log(this.responseText);
}
});
xhr.open('POST', 'https://{base_url}.infobip.com/email/1/send', false);
xhr.setRequestHeader('authorization', 'Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==');
xhr.setRequestHeader('accept', 'application/json');
xhr.send(createFormData(data));
You should use https from nodejs.
Here an example code to getting started. For infopib it seems to be so normal Post request.
I tried to create an account on this page, but registration seems to can be completed only over sales. So I couldn't provide a working example...
This is why I can only provide a general example how to make an https POST call, which should be a good starting point to develop your solution:
const https = require('https')
const data = JSON.stringify({
todo: 'Buy the milk'
})
const options = {
hostname: 'yourURL.com',
port: 443,
path: '/todos',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': data.length
}
}
const req = https.request(options, (res) => {
console.log(`statusCode: ${res.statusCode}`)
res.on('data', (d) => {
process.stdout.write(d)
})
})
req.on('error', (error) => {
console.error(error)
})
req.write(data)
req.end()

Pure JavaScript Send POST Data Without a Form

Is there a way to send data using the POST method without a form and without refreshing the page using only pure JavaScript (not jQuery $.post())? Maybe httprequest or something else (just can't find it now)?
You can send it and insert the data to the body:
var xhr = new XMLHttpRequest();
xhr.open("POST", yourUrl, true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify({
value: value
}));
By the way, for get request:
var xhr = new XMLHttpRequest();
// we defined the xhr
xhr.onreadystatechange = function () {
if (this.readyState != 4) return;
if (this.status == 200) {
var data = JSON.parse(this.responseText);
// we get the returned data
}
// end of state change: it can be after some time (async)
};
xhr.open('GET', yourUrl, true);
xhr.send();
The Fetch API is intended to make GET requests easy, but it is able to POST as well.
let data = {element: "barium"};
fetch("/post/data/here", {
method: "POST",
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(data)
}).then(res => {
console.log("Request complete! response:", res);
});
If you are as lazy as me (or just prefer a shortcut/helper):
window.post = function(url, data) {
return fetch(url, {method: "POST", headers: {'Content-Type': 'application/json'}, body: JSON.stringify(data)});
}
// ...
post("post/data/here", {element: "osmium"});
You can use the XMLHttpRequest object as follows:
xhr.open("POST", url, true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
xhr.send(someStuff);
That code would post someStuff to url. Just make sure that when you create your XMLHttpRequest object, it will be cross-browser compatible. There are endless examples out there of how to do that.
Also, RESTful lets you get data back from a POST request.
JS (put in static/hello.html to serve via Python):
<html><head><meta charset="utf-8"/></head><body>
Hello.
<script>
var xhr = new XMLHttpRequest();
xhr.open("POST", "/postman", true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify({
value: 'value'
}));
xhr.onload = function() {
console.log("HELLO")
console.log(this.responseText);
var data = JSON.parse(this.responseText);
console.log(data);
}
</script></body></html>
Python server (for testing):
import time, threading, socket, SocketServer, BaseHTTPServer
import os, traceback, sys, json
log_lock = threading.Lock()
log_next_thread_id = 0
# Local log functiondef
def Log(module, msg):
with log_lock:
thread = threading.current_thread().__name__
msg = "%s %s: %s" % (module, thread, msg)
sys.stderr.write(msg + '\n')
def Log_Traceback():
t = traceback.format_exc().strip('\n').split('\n')
if ', in ' in t[-3]:
t[-3] = t[-3].replace(', in','\n***\n*** In') + '(...):'
t[-2] += '\n***'
err = '\n*** '.join(t[-3:]).replace('"','').replace(' File ', '')
err = err.replace(', line',':')
Log("Traceback", '\n'.join(t[:-3]) + '\n\n\n***\n*** ' + err + '\n***\n\n')
os._exit(4)
def Set_Thread_Label(s):
global log_next_thread_id
with log_lock:
threading.current_thread().__name__ = "%d%s" \
% (log_next_thread_id, s)
log_next_thread_id += 1
class Handler(BaseHTTPServer.BaseHTTPRequestHandler):
def do_GET(self):
Set_Thread_Label(self.path + "[get]")
try:
Log("HTTP", "PATH='%s'" % self.path)
with open('static' + self.path) as f:
data = f.read()
Log("Static", "DATA='%s'" % data)
self.send_response(200)
self.send_header("Content-type", "text/html")
self.end_headers()
self.wfile.write(data)
except:
Log_Traceback()
def do_POST(self):
Set_Thread_Label(self.path + "[post]")
try:
length = int(self.headers.getheader('content-length'))
req = self.rfile.read(length)
Log("HTTP", "PATH='%s'" % self.path)
Log("URL", "request data = %s" % req)
req = json.loads(req)
response = {'req': req}
response = json.dumps(response)
Log("URL", "response data = %s" % response)
self.send_response(200)
self.send_header("Content-type", "application/json")
self.send_header("content-length", str(len(response)))
self.end_headers()
self.wfile.write(response)
except:
Log_Traceback()
# Create ONE socket.
addr = ('', 8000)
sock = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(addr)
sock.listen(5)
# Launch 100 listener threads.
class Thread(threading.Thread):
def __init__(self, i):
threading.Thread.__init__(self)
self.i = i
self.daemon = True
self.start()
def run(self):
httpd = BaseHTTPServer.HTTPServer(addr, Handler, False)
# Prevent the HTTP server from re-binding every handler.
# https://stackoverflow.com/questions/46210672/
httpd.socket = sock
httpd.server_bind = self.server_close = lambda self: None
httpd.serve_forever()
[Thread(i) for i in range(10)]
time.sleep(9e9)
Console log (chrome):
HELLO
hello.html:14 {"req": {"value": "value"}}
hello.html:16
{req: {…}}
req
:
{value: "value"}
__proto__
:
Object
Console log (firefox):
GET
http://XXXXX:8000/hello.html [HTTP/1.0 200 OK 0ms]
POST
XHR
http://XXXXX:8000/postman [HTTP/1.0 200 OK 0ms]
HELLO hello.html:13:3
{"req": {"value": "value"}} hello.html:14:3
Object { req: Object }
Console log (Edge):
HTML1300: Navigation occurred.
hello.html
HTML1527: DOCTYPE expected. Consider adding a valid HTML5 doctype: "<!DOCTYPE html>".
hello.html (1,1)
Current window: XXXXX/hello.html
HELLO
hello.html (13,3)
{"req": {"value": "value"}}
hello.html (14,3)
[object Object]
hello.html (16,3)
{
[functions]: ,
__proto__: { },
req: {
[functions]: ,
__proto__: { },
value: "value"
}
}
Python log:
HTTP 8/postman[post]: PATH='/postman'
URL 8/postman[post]: request data = {"value":"value"}
URL 8/postman[post]: response data = {"req": {"value": "value"}}
You can use XMLHttpRequest, fetch API, ...
If you want to use XMLHttpRequest you can do the following
var xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify({
name: "Deska",
email: "deska#gmail.com",
phone: "342234553"
}));
xhr.onload = function() {
var data = JSON.parse(this.responseText);
console.log(data);
};
Or if you want to use fetch API
fetch(url, {
method:"POST",
body: JSON.stringify({
name: "Deska",
email: "deska#gmail.com",
phone: "342234553"
})
}).then(result => {
// do something with the result
console.log("Completed with result:", result);
}).catch(err => {
// if any error occured, then catch it here
console.error(err);
});
There is an easy method to wrap your data and send it to server as if you were sending an HTML form using POST.
you can do that using FormData object as following:
data = new FormData()
data.set('Foo',1)
data.set('Bar','boo')
let request = new XMLHttpRequest();
request.open("POST", 'some_url/', true);
request.send(data)
now you can handle the data on the server-side just like the way you deal with reugular HTML Forms.
Additional Info
It is advised that you must not set Content-Type header when sending FormData since the browser will take care of that.
Did you know that JavaScript has it's built-in methods and libs to create forms and submit them?
I am seeing a lot of replies here all asking to use a 3rd party library which I think is an overkill.
I would do the following in pure Javascript:
<script>
function launchMyForm()
{
var myForm = document.createElement("FORM");
myForm.setAttribute("id","TestForm");
document.body.appendChild(myForm);
// this will create a new FORM which is mapped to the Java Object of myForm, with an id of TestForm. Equivalent to: <form id="TestForm"></form>
var myInput = document.createElement("INPUT");
myInput.setAttribute("id","MyInput");
myInput.setAttribute("type","text");
myInput.setAttribute("value","Heider");
document.getElementById("TestForm").appendChild(myInput);
// To submit the form:
myForm.method = "POST";
myForm.action = "whatever.aspx"; // or "response.php"
myForm.submit();
// This will create an INPUT equivalent to: <INPUT id="MyInput" type="text" value="Heider" /> and then assign it to be inside the TestForm tags.
}
</script>
This way (A) you don't need to rely on 3rd parties to do the job. (B) It's all built-in to all browsers, (C) faster, (D) it works, feel free to try it out.
I hope this helps.
H
navigator.sendBeacon()
If you simply need to POST data and do not require a response from the server, the shortest solution would be to use navigator.sendBeacon():
const data = JSON.stringify({
example_1: 123,
example_2: 'Hello, world!',
});
navigator.sendBeacon('example.php', data);
The most popular answers here do not show how to get data back from the POST. Also, the popular "fetch" solutions do not work in the latest version of Chrome when sending data to the latest version of NodeJS unless you pass headers and also unwrap the response.json() promise. Also, the popular answers do not use async/await.
Here is the cleanest and most complete solution I could come up with that works.
async function postJsonData(jsonObject) {
const response = await fetch("/echo", {
method: "POST",
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(jsonObject)
});
const actualResponse = await response.json();
}
Here is a nice function you (or anyone else) could use in their code:
function post(url, data) {
return new Promise((res, rej) => {
let stringified = "";
for (const [key, value] of Object.entries(data))
stringified += `${stringified != '' ? '&' : ''}${key}=${value}`
const xhr = new XMLHttpRequest();
xhr.onreadystatechange = () => {
if (xhr.readyState == 4)
if (xhr.status == 200)
res(xhr.responseText)
else
rej({ code: xhr.status, text: xhr.responseText })
}
xhr.open("POST", url, true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(stringified);
})
}
const data = { username: 'example' };
fetch('https://example.com/profile', {
method: 'POST', // or 'PUT'
headers: {
' Content-Type': 'application/json',
},
body: JSON.stringify(data),
})
.then(response => response.json())
.then(data => {
console.log('Success:', data);
})
.catch((error) => {
console.error('Error:', error);
});
You can also use this: https://github.com/floscodes/JS/blob/master/Requests.js
You can easily send a http-Request. Just use:
HttpRequest("https://example.com", method="post", data="yourkey=yourdata");
That's it! It should even work if the site is CSRF-protected.
Or just send a GET-Request by using
HttpRequest("https://example.com", method="get");
use this func of jbezz library
var makeHttpObject = function () {
try {return new XMLHttpRequest();}
catch (error) {}
try {return new ActiveXObject("Msxml2.XMLHTTP");}
catch (error) {}
try {return new ActiveXObject("Microsoft.XMLHTTP");}
catch (error) {}
throw new Error("Could not create HTTP request object.");
}
function SendData(data){
let type = (data.type ? data.type : "GET")
let DataS = data.data;
let url = data.url;
let func = (data.success ? data.success : function(){})
let funcE =(data.error ? data.error : function(){})
let a_syne = (data.asyne ? data.asyne : false);
let u = null;
try{u = new URLSearchParams(DataS).toString();}catch(e){u = Object.keys(DataS).map(function(k) {return encodeURIComponent(k) + '=' + encodeURIComponent(DataS[k])}).join('&')}
if(type == "GET"){url +="?"+u}
const xhttp = makeHttpObject();
xhttp.onload = function(){func(this.responseText)}
xmlHttp.onreadystatechange = function() {if (xmlHttp.readyState == 4)
{if(xmlHttp.status !== 200){funcE(xmlHttp.statusText)}}}
xhttp.open(type,url,a_syne);
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhttp.send(u);
}
use this to run :
SendData({
url:"YOUR_URL",
asyne:true,
type:"POST", // or GET
data:{
username:"ali",
password:"mypass" // Your Data
},
success:function(Result){
console.log(Result)
},
error:function(e){
console.log("We Have Some Error")
}
});
Or
download jbezz and add to your page.
download link : github.com
use :
$$.api({
url:"YOUR_URL",
asyne:true,
type:"POST", // or GET
data:{
username:"ali",
password:"mypass" // Your Data
},
success:function(Result){
console.log(Result)
},
error:function(e){
console.log("We Have Some Error")
}
});

Categories