I've got the following code in Python:
import requests
fileslist = [('file[]',('user_query.txt', open('user_query.txt', 'rb'), 'text/plain')),
('file[]',('wheatData.csv', open('wheatData.csv', 'rb'), 'text/csv')),]
r = requests.post('url',
files=fileslist)
And I'm trying to convert it to a node.JS version. So far I've got this:
var request = require('request');
var fs = require('fs');
var req = request.post(url, function (err, resp, body) {
if (err) {
console.log('Error!');
} else {
console.log(body);
}
});
var form = req.form();
form.append('wheatData.csv', fs.createReadStream('wheatData.csv'));
form.append('user_query.txt', fs.createReadStream('user_query.txt'));
What am I doing wrong?
This is how you do it using express and body-parser module to parse the post request and fetch the files you need .This is what goes in your node.js server.
Import all the modules :
var express = require("express");
var bodyParser = require('body-parser')
var app = express(); //init express app()
var util = require('util');
//APP CONFIGURATION >> Skip this if you dont want CORS
app.use(express.static('app')); // use this as resource directory
app.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
Configure the post Url :
//url => url/for/mypostrequest
app.post(url, done, function (req, res) {
//Handle the post request body here...
var filesUploaded = 0;
//check if files present
if (Object.keys(req.files).length === 0) {
console.log('no files uploaded');
} else {
console.log(req.files);
var files = req.files.file1;
//If multiple files store in array..
if (!util.isArray(req.files.file1)) {
files = [req.files.file1];
}
filesUploaded = files.length;
}
res.json({message: 'Finished! Uploaded ' + filesUploaded + ' files. Route is /files1'});
});
Make sure all the modules are installed and present as dependencies in package.json
CODE for making an api post call from node..
Include the http module first in your server .
var http = require('http');
var querystring = require('querystring');
var fs = require('fs');
Theninclude following code to make a post request from node server
var file1, file2;
//Read first File ...
fs.readFileSync('wheatData.csv', function (err, data) {
if (err) {
console.log('Error in file reading...');
}
file1 = data;
//Read second file....
fs.readFileSync('wheatData.csv', function (err, data) {
if (err) {
console.log('Error in file reading...');
}
file2 = data;
//Construct the post request data..
var postData = querystring.stringify({
'msg': 'Hello World!',
'file1': file1,
'file2': file2
});
var options = { //setup option for you request
hostname: 'www.path/to/api/',
port: 80,
path: '/upload',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': postData.length
}
};
var req = http.request(options, function (res) {
console.log('STATUS:' + res.statusCode);
console.log('HEADERS:' + JSON.stringify(res.headers));
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log('BODY: ' + chunk);
});
res.on('end', function () {
console.log('No more data in response.');
});
});
req.on('error', function (e) {
console.log('problem with request: ' + e.message);
});
// write data to request body
req.write(postData);
req.end();
});
});
Please note that code has not been tested on live server , you may need to make alteration as per your configuration.
Also you can use other libraries like request or needler..etc to make post calls from node server as suggested in this post.
Related
Hi I’m figuring out how to share Plex library in dart.
I'm helping myself with this working script in python ( it works)
https://gist.github.com/JonnyWong16/f8139216e2748cb367558070c1448636
unfortunately my code returns an http error 400, bad request
note: When I run the dart code there are no shared library.
maybe the payload is not correct :|
Thank for any help
import 'package:http/http.dart' as http;
class Server {
String token, ip, port;
Server(this.ip, this.port, this.token);
share() async {
var server_id = '00000000000000000000000000000000'; fake id
var library_section_ids = '97430074'; // right id , it works in python
var invited_id = '50819899'; // right id , it works in python
var headers = {
'Accept': 'application/json',
'X-Plex-Token': token,
};
var data =
'["server_id": $server_id,'
' "shared_server":["library_section_ids":[$library_section_ids],'
' "invited_id":$invited_id]';
var res = await http.post(
Uri.parse(
'https://plex.tv/api/servers/$server_id/shared_servers/'),
headers: headers,
body: data);
if (res.statusCode != 200) {
throw Exception('http.post error: statusCode= ${res.statusCode}');
}
print(res.body);
}
}
void main(List<String> arguments) async {
var srv = Server('xxx.yyy.xxx.yyy', '32400', '000000000-1111');
await srv.share();
}
The old code has a few bug and don't encode perfectly the data
I solved with 'dio' package and this link helped me a lot https://reqbin.com/
If the user has no shared library this code add a new one
import 'package:dio/dio.dart';
class Server {
String token;
Server(this.token);
test() async {
var serverId = '';
var librarySectionIds = ;
var invitedId = ;
var dio = Dio();
var data = {
"server_id": serverId,
"shared_server": {
"library_section_ids": librarySectionIds,
"invited_id": invitedId
}
};
dio.options.headers['Accept'] = 'application/json';
dio.options.headers["authorization"] = "Bearer $token";
var response = await dio.post(
'https://plex.tv/api/servers/$serverId/shared_servers/',
data: data);
print(response);
}
I want the following code to be translated into GAS from python. I wrote the GAS version pasted below but it is not working. It must be something simple but I don't know the reason why I get this error. Any advice will be appreciated. Thanks.
import requests
requestId = "*******************"
url = "http://myapi/internal/ocr/"+requestid+"/ng"
payload={}
headers = {
'X-Authorization': 'abcdefghijklmn'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
I wrote this at the moment but I get bad request error.
function sending(yesorno, requestId) {
var requestId = "*******************"
var STAGING_KEY = "abcdefghijklmn"
var url = url = "http://myapi/internal/ocr/"+requestId+"/ng"
var data = {}
var options = {
'muteHttpExceptions': true,
'method': 'post',
'payload': JSON.stringify(data),
'headers': {
'X-Authorization': STAGING_KEY
}
};
//Error processing
try {
var response = JSON.parse(UrlFetchApp.fetch(url, options));
if (response && response["id"]) {
return 'sent';
} else {
//reportError("Invalid response: " + JSON.stringify(response));
//return 'error';
Logger.log('error')
}
} catch (e) {
//reportError(e.toString());
//return 'error';
Logger.log('error')
}
}
Modified Code
function sending() {
var requestId = "*************************"
var STAGING_KEY = "abcdefghijklmn"
var url = "http://myapi/internal/ocr/"+requestId+"/ng";
var data = {}
var options = {
'muteHttpExceptions': true,
'method': 'post',
'payload': data,
'headers': {
'X-Authorization': STAGING_KEY
}
};
try {
var response = JSON.parse(UrlFetchApp.fetch(url, options).getContentText());
Logger.log(response)
if (response && response["id"]) {
return 'sent';
} else {
//reportError("Invalid response: " + JSON.stringify(response));
//return 'error';
Logger.log('error1')
}
} catch (e) {
//reportError(e.toString());
//return 'error';
Logger.log('error2: '+ e.toString())
}
}
Error
error2: Exception: Bad request:
I understood your situation as follows.
Your python script works fine.
You want to convert the python script to Google Apps Script.
When your Google Apps Script is run, an error Exception: Bad request: occurs.
In this case, how about the following modification? When response = requests.request("POST", url, headers=headers, data=payload) is used with payload={}, I think that at Google Apps Script, it's 'payload': {}.
Modified script:
function sending() {
var requestId = "*******************"
var STAGING_KEY = "abcdefghijklmn"
var url = "http://myapi/internal/ocr/" + requestId + "/ng"
var data = {}
var options = {
'muteHttpExceptions': true,
'method': 'post',
'payload': data,
'headers': {
'X-Authorization': STAGING_KEY
}
};
try {
var response = JSON.parse(UrlFetchApp.fetch(url, options).getContentText());
console.log(response)
if (response && response["id"]) {
return 'sent';
} else {
//reportError("Invalid response: " + JSON.stringify(response));
//return 'error';
Logger.log('error')
}
} catch (e) {
//reportError(e.toString());
//return 'error';
Logger.log('error')
}
}
Note:
By the above modification, the request of Google Apps Script is the same as that of the python script. But if an error occurs, please check the URL and your STAGING_KEY, again. And, please check whether the API you want to use can access from the Google side.
Reference:
fetch(url, params)
I have a web scraping application written completely in python. The information that I am web scraping is behind a login and I am using Request.session to save login sessions. I am trying to port the code to Node.js and wasn't able to find anything similar to request.session on Node.js. Please let me know if such a thing exists. Thank you.
Your best bet is using axios, which allows for extensive customization of request headers and types of authentication.
You can add axios-cookiejar for cookie management.
Simple example:
const axios = require('axios').default;
const axiosCookieJarSupport = require('axios-cookiejar-support').default;
axiosCookieJarSupport(axios);
// you can add an Authorization header to all requests:
// axios.defaults.headers.common['Authorization'] = 'Bearer token';
const cookie = 'lang=en; token=hello';
const body = {message: 'I\'m a message body'};
axios.post(url, body, {
auth: {
username: 'username',
password: 'mypassword',
},
headers: {
'Cookie': cookie,
'Content-Type': 'application/json',
},
})
.then(res => console.log(res))
.catch(err => console.error(err));
Old Answer:
I believe the Request object of the default HTTP server does not have what you are looking for.
But if you opted to use the Express framework, you could find similar functionalities in the express-session package.
To ilustrate it's capabilities and simplicity, here's a slightly tweaked version of the code example provided in their documentation:
const express = require('express')
const parseurl = require('parseurl')
const session = require('express-session')
const app = express()
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true,
}));
app.use((req, res, next) => {
if (!req.session.views) {
req.session.views = {}
}
// get the url pathname
const pathname = parseurl(req).pathname;
// count the views
req.session.views[pathname] = (req.session.views[pathname] || 0) + 1;
next();
});
app.get('/foo', (req, res, next) => {
res.send('you viewed this page ' + req.session.views['/foo'] + ' times');
});
app.get('/bar', (req, res, next) => {
res.send('you viewed this page ' + req.session.views['/bar'] + ' times');
});
app.use((req, res, next) => {
if (res.headersSent) {
return next();
} else {
console.error('Not found');
const err = new Error('Not Found');
err.status = 404;
return next(err);
}
});
app.use((err, req, res, next) => {
console.error(req.app.get('env') === 'production' ? err.message : err.stack);
if (res.headersSent) {
return next(err);
}
res.status(err.status || 500);
res.send(`${err.status} - ${err.message}`);
});
const http = require('http');
const server = http.createServer(app).listen(3000);
server.on('error', (e) => {
console.log('>>> Server error');
console.error(e);
});
console.log(`>>> Server running on localhost:3000`);
I have been trying to solve this for the past few hours.
I am using the Heroku S3 python app direct upload method outlined here.
Basically, I have a file input which I get the file from with
$('#files').on('change', function() {
var files = document.getElementById("files").files;
var file = files[0];
if(!file){
return alert("No file selected.");
}
getSignedRequest(file);
})
In getSignedRequest, I make a request to my sign_s3 route
function getSignedRequest(file){
var xhr = new XMLHttpRequest();
xhr.open("GET", "/sign_s3?file_name="+file.name+"&file_type="+file.type);
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
if(xhr.status === 200){
var response = JSON.parse(xhr.responseText);
uploadFile(file, response.data, response.url);
}
else{
alert("Could not get signed URL.");
}
}
};
xhr.send();
}
The sign_s3 route is defined as follows
#main.route('/sign_s3/')
def sign_s3():
S3_BUCKET = os.environ.get('S3_BUCKET')
file_name = request.args.get('file_name')
file_type = request.args.get('file_type')
s3 = boto3.client('s3')
presigned_post = s3.generate_presigned_post(
Bucket = S3_BUCKET,
Key = file_name,
Fields = {"acl": "public-read", "Content-Type": file_type},
Conditions = [
{"acl": "public-read"},
{"Content-Type": file_type}
],
ExpiresIn = 3600
)
return json.dumps({
'data': presigned_post,
'url': 'https://%s.s3.amazonaws.com/%s' % (S3_BUCKET, file_name)
})
The uploadFile function is defined as follows
function uploadFile(file, s3Data, url){
var xhr = new XMLHttpRequest();
xhr.open("POST", s3Data.url);
var postData = new FormData();
for(key in s3Data.fields){
postData.append(key, s3Data.fields[key]);
}
postData.append('file', file);
console.log(file);
xhr.onreadystatechange = function() {
if(xhr.readyState === 4){
if(xhr.status === 200 || xhr.status === 204){
document.getElementById("preview").src = url;
document.getElementById("avatar-url").value = url;
}
else{
alert("Could not upload file.");
}
}
};
xhr.send(postData);
}
});
My bucket CORS config is as follows
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>http://localhost:5000</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
But I keep getting the following error upon fileUpload
Failed to load https://mhealth-beta-1.s3.amazonaws.com/: Redirect from 'https://mhealth-beta-1.s3.amazonaws.com/' to 'https://mhealth-beta-1.s3-us-west-2.amazonaws.com/' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:5000' is therefore not allowed access.
The error is mentioning a redirect. I'm not familiar with how 302 redirects interact with CORS but try this:
In your backend route, use the dns name including the region.
so 'https://%s.s3.%s.amazonaws.com/%s' % (S3_BUCKET, region, file_name)
i just tested out a script i made. it is in python. i use ajax, to send a request and try and get the result.
function ajaxFunction(){
var ajaxRequest;
var e = document.getElementById("ktype");
var ktype = e.options[e.selectedIndex].value;
var acookie = document.getElementById("acookie").value;
alert (ktype +"\n" + acookie);
try{
ajaxRequest = new XMLHttpRequest();
} catch (e){
try{
ajaxRequest = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try{
ajaxRequest = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e){
return false;
}
}
}
ajaxRequest.onreadystatechange = function(){
if (ajaxRequest.readyState < 4){
document.getElementById("resp").innerHTML = "<center><img src='loading.gif' style='max-width:60px; max-height:60px;'></center>";
}
if(ajaxRequest.readyState == 4){
document.getElementById("resp").innerHTML = ajaxRequest.responseText;
}
}
ajaxRequest.open("POST", "kindle.py", true);
ajaxRequest.setRequestHeader("Content-type","application/x-www-form-urlencoded");
ajaxRequest.send("amzcookie=" + acookie + "&ktype=" + ktype);
}
the python script uses CGI. no web framework like django.
when i do this request it just prints the contents of the python file. no code is executed.
You should use JQuery for that ... instead of writing your own Ajax request, it can be written in a line:
$.post('link-to-my-python-script',{data},
function(answer){
// process your request here ..
});
You can read more about that here: JqueryPost