I have an Amcrest IP Camera. I would like to stream video to my web page.
Its url is rtsp://mycamera.com:5554/stream
In order to get the stream of the camera, the camera has a following API http://mycamera.com/video.mjpg
It requires the basic authentication to work.
By formatting the URL and putting it into the image tag like below, I can make it work on Firefox, Safari
<img src="http://username:password#mycamera.com/video.mjpg" />
However, Chrome (v.40 on mine) does not allow this kind of URL, the browser will promt the user password form to be filled, or simply refuses the request. Setting header Authorization: "Basic encode64(username, password)" in the script does not help, the URL always return 401 error (Unauthorized)
Sometimes, it raises the CORS error. If my website is running with HTTPS, the HTTP API call will get blocked by the browser.
Disable authentication of IP camera:
If the camera does not have that option on the admin panel, just add an user without a password with any username like "none", then we can setup like this
<iframe src="http://none:#mycamera.com/video.mjpg" width="1280" height="768"></iframe>
Without password, my Chrome no longer throws the user name/password. (tested on Chrome of Windows and MacOSX & Safari)
Proxy the output to my own website's server:
Download the framework CORS of the mohsen1
Install node js and run this server on the same with domain of the website. We need to edit the index.js file as below
var fs = require('fs');
var request = require('request');
var http = require('http');
var https = require('https');
var privateKey = fs.readFileSync('/var/private_key.pem', 'utf8');
var certificate = fs.readFileSync('/var/certificate.crt, 'utf8');
var credentials = {key: privateKey, cert: certificate};
var express = require('express');
var proxy_http_port = 9009
var proxy_https_port = 9443
var app = express();
// your express configuration here
var auth = "";
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();
});
var t = app.get('/', function (req, res, next) {
var username = "";
var password = "";
if (req.query.auth) {
username = req.query.auth.split(":")[0];
password = req.query.auth.split(":")[1];
auth = 'Basic ' + new Buffer(username + ':' + password).toString('base64');
res.header('Authorization', auth);
} else {
res.send('please specify auth query param');
}
if (req.query.url) {
var options = {
method: 'GET',
url: req.query.url,
headers: {
"Authorization": auth,
//'User-Agent': req.headers['user-agent']
},
encoding: null
};
var r = request(options, function callback(error, response, body) {
if (!error && response.statusCode == 200) {
res.write(body);
delete response.headers['access-control-allow-origin'];
}
}).pipe(res);
} else {
res.send('You have to specify URL query');
}
});
http.globalAgent.maxSockets = 100;
var httpServer = http.createServer(app);
var httpsServer = https.createServer(credentials, app);
httpServer.listen(proxy_http_port);
httpsServer.listen(proxy_https_port);
Encode the video stream URL below:
http://mycamera.com/video.mjpg
to:
http%3A%2F%2Fmycamera.com%2Fvideo.mjpg
The URL of stream video should be
https://mywebsite.com:9443/?auth=username:password&url=(put above encoded video URL here)
THe advantage of this approach is to bypass most of problems around and get rid of the errors(CORS, HTTPS) because my website will request to its own server
The drawback is the video would be fetch twice, it caused delay pretty much.
Error 401 means invalid credentials so there's a good chance you are simply not formatting the basic auth string correctly. The header format should be Authorization Basic [base64 encoded username:password] using a colon symbol : to separate the two before encoding that entire string into base 64.
For example the resulting header should look something like this:
Authorization: Basic QWxhZGRpbjpPcGVuU2VzYW1l
You can try installing the Chrome "Advanced REST Client" plugin and use that plugin to test accessing your URL link with basic auth parameters. If you can get it to work with the REST client plugin then go back and update your script to fix the format of the auth headers.
Link to Advanced REST Client:
https://chrome.google.com/webstore/detail/advanced-rest-client/hgmloofddffdnphfgcellkdfbfbjeloo?hl=en-US
Link to auth headers format info:
https://en.wikipedia.org/wiki/Basic_access_authentication
Related
I have a flutter app and I'm using back4app.com and Parse RESTful api to register my users, I have read their docs about logging in users but I dont know how to pass my username and password in URL parameters as JSON encoded :
I tried this method:
Future <void>loginMethod(String username,String password) async {
var url = Uri.parse('https://myshoppingapp.b4a.io/login/$username:$password');
final response = await http.get(url, headers: {
'X-Parse-Application-Id': kParseApplicationId,
'X-Parse-REST-API-Key': kParseRestApiKey,
'Content-Type': 'application/json'
},);
final exData = jsonDecode(response.body);
print(exData);
but I've got some errors
Don't use the GET method while sending your personal data to the server.
GET method data is sent data to the server followed by the URL like append with URL request which will be seen to everyone like below.
var url = Uri.parse('https://myshoppingapp.b4a.io/login/$username:$password');
This is how your personal data can be readable from a URL in a GET Method.
'https://myshoppingapp.b4a.io/login/Mehran#metra.org:abcd12345'
For login requests, we should use the POST method. Because our login data is secure which needs security. When using the POST method the data is sent to the server in a bundle.
Future loginMethod(String username,String password) async {
var res = await http.post(Uri.parse('https://myshoppingapp.b4a.io/login/'),
body: {"username": username, "password": password});
print('res : ${res.body}');
if (res.statusCode == 200){ final exData = jsonDecode(res.body);
print(exData);
return res.body;
} else{
final exData = jsonDecode(res.body);
print(exData);
return res.statusCode;
}
}
for HTTP basic authentication
final loginUrl = Uri(scheme: 'https', host: 'example.com', port: 8080, userInfo: 'username:password')
http.get(loginUrl)
but pass username and password via url is not recommended cause it's not safe.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication#access_using_credentials_in_the_url
so you should do it by using post formdata.
I am using the following javascript on a webpage to send information to a Node.js server upon a "click" on an image. This is using a 'POST' request.
<script>
function rerouter(_sent) {
var _people = <%- JSON.stringify(member_list) %>;
//convert the passed ('member_list') array into a JSON string...
var _attend = <%- JSON.stringify(online) %>;
//convert the passed ('online') array into a JSON string...
var splits = _sent.id.split("_"); //"split" on "underscore ('_')"
if (_people.indexOf(splits[1]) != -1) {
//**SEND INFO TO SERVER...
var available = _attend[_people.indexOf(splits[1])];
var response = fetch("members/pages/:" + splits[1] + "/presence/:" + available, {
method: 'POST',
headers: {
'Content-Type': 'text/plain;charset=utf-8'
}
});
//**
} //'_people' array contains the member name ('splits[1]')...
}
</script>
And here I handle the request in my Node.js server code:
var bodyParser = require('body-parser')
// create application/json parser
var jsonParser = bodyParser.json()
// create application/x-www-form-urlencoded parser
var urlencodedParser = bodyParser.urlencoded({ extended: false })
app.post('/members/pages/:membername/presence/:online', urlencodedParser, function (req, res) {
console.log("I RECEIVED FROM CLIENT THE FOLLOWING:")
console.log(req.params)
console.log(req.body)
res.redirect('/_landing');
})
Here is my console output:
I RECEIVED FROM CLIENT THE FOLLOWING:
{ membername: ':Nica', online: ':Yes' }
{}
As can be seen from my output, the POST route does seem to be functional, somewhat. However my 'redirect' command does NOT execute...the webpage does not change to the '_landing' page as it should...I think it may be because I am using 'fetch' to send the POST request...??? Can somebody verify if that is the cause (or another issue is the cause) and how I might be able to correct the issue?
In addition why does my 'params' include the colons (":") when I log to the console...is that standard? I would not think it would include the colons in the log, only the actual data.
Basically it seems my POST is almost working...but not exactly. Any suggestions would be greatly appreciated. I thank you in advance.
UPDATE: I have made some changes and my POST seems to be working fine now. In my frontend webpage I use the following to make the HTTP POST request:
<script>
function rerouter(_sent) {
var _people = <%- JSON.stringify(member_list) %>;
//convert the passed ('member_list') array into a JSON string...
var _attend = <%- JSON.stringify(online) %>;
//convert the passed ('online') array into a JSON string...
var splits = _sent.id.split("_"); //"split" on "underscore ('_')"
if (_people.indexOf(splits[1]) != -1) {
//**SEND INFO TO SERVER...
var available = _attend[_people.indexOf(splits[1])];
fetch('/members/pages/callup', {
method: 'post',
headers: {
'Accept': 'application/json, text/plain, */*',
'Content-Type': 'application/json'
},
body: JSON.stringify({name: splits[1], presence: available, str: 'Some string: &=&'})
})
//**
} //'_people' array contains the member name ('splits[1]')...
}
</script>
...And modified my route handler in my Node.js script:
// create application/json parser
var jsonParser = bodyParser.json()
app.post('/members/pages/callup', jsonParser, function (req, res) {
console.log("I RECEIVED FROM CLIENT THE FOLLOWING:")
console.log(req.body)
res.redirect('/_landing');
})
This is functional...to receive the data sent from the frontend webpage.
The only remaining problem is why does the 'redirect' not fire...??? I still have a feeling that by using a 'fetch' that somehow this is interfering with the page redirection...? A fetch would normally be used to wait for a response from the server, in my case I am not interested in that functionality I just want to send data one-way from frontend to backend...and then redirect the frontend page. I cannot think of any other reason why the redirect does not fire...?
Make extented:true instead of false as,
var urlencodedParser = bodyParser.urlencoded({ extended: true }) and move this line above of the below statement,
var jsonParser = bodyParser.json() and check if it works.
And finally change your headers here from,
headers: {
'Content-Type': 'text/plain;charset=utf-8'
}
To,
headers: {
'Content-Type': 'application/json'
}
Hope this will resolve the issue.
I'm running this little node express server, which is supposed to check if the voucher is valid later and then send an answer back to the client
this is my code
app.post('/voucher', function (request, response) {
response.setHeader('Access-Control-Allow-Origin', '*');
response.setHeader('Access-Control-Request-Method', '*');
response.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET');
response.setHeader('Access-Control-Allow-Headers', 'authorization, content-type');
if ( request.method === 'OPTIONS' ) {
response.writeHead(200);
response.end();
return;
}
console.log(request)
let results;
let body = [];
request.on('data', function(chunk) {
body.push(chunk);
}).on('end', function() {
results = Buffer.concat(body).toString();
// results = JSON.parse(results);
console.log('#### CHECKING VOUCHER ####', results)
let success = {success: true, voucher: {name: results,
xxx: 10}}
success = qs.escape(JSON.stringify(success))
response.end(success)
} )
}
);
It is obviously just an example and the actual check is not implemented yet. So far so good.
Now on the client side where I work with REACT, I can not seem to decode the string I just send there.
there I'm doing this
var voucherchecker = $.post('http://localhost:8080/voucher', code , function(res) {
console.log(res)
let x = JSON.parse(res)
console.log(x)
console.log(qs.unescape(x))
It gives me the error
Uncaught SyntaxError: Unexpected token % in JSON at position 0
When I do it the other way arround
let x = qs.unescape(res)
console.log(x)
console.log(JSON.parse(x))
Than it tells me
Uncaught TypeError: _querystring2.default.unescape is not a function
Maybe you can help me? I don't know what the issue is here. Thank you.
Also another question on this behalf, since I'm only a beginner. Is there smarter ways to do such things than I'm doing it now? I have react which renders on the client and I have a mini express server which interacts a few times with it during the payment process.
The both run on different ports.
What would be the standard way or best practice to do such things?
I'm a bit perplexed as to why your backend code has so much going on in the request.
Since you asked for if there is a different way to write this, I will share with you how I would write it.
Server
It seems that you want your requests to enable CORS, it also seems that you originally wanted to parse a JSON in your request body.
This is how I would recommend you re-write your endpoint
POST /voucher to take a request with body JSON
{
code: "xxxxx"
}
and respond with
{
success: true,
voucher: {
name: results,
xxx: 10
}
}
I would recommend you use express's middleware feature as you will probably use CORS and parse JSON in most your requests so in your project I would.
npm install body-parser
npm install cors
then in your app initialization
var bodyParser = require('body-parser')
var cors = require('cors')
var app = express()
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))
// parse application/json you can choose to just pars raw text as well
app.use(bodyParser.json())
// this will set Access-Control-Allow-Origin * similar for all response headers
app.use(cors())
You can read more about body-parser and cors in their respective repos, if you don't want to use them I would still recommend you use your own middleware in order to reduse future redundancy in your code.
So far this will substitute this part of your code
response.setHeader('Access-Control-Allow-Origin', '*');
response.setHeader('Access-Control-Request-Method', '*');
response.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET');
response.setHeader('Access-Control-Allow-Headers', 'authorization, content-type');
if ( request.method === 'OPTIONS' ) {
response.writeHead(200);
response.end();
return;
}
console.log(request)
let results;
let body = [];
request.on('data', function(chunk) {
body.push(chunk);
}).on('end', function() {
results = Buffer.concat(body).toString();
// results = JSON.parse(results);
Now your route definition can just be
app.post('/voucher', function (request, response) {
var result = request.body.code // added by body-parser
console.log('#### CHECKING VOUCHER ####', result)
// express 4+ is smart enough to send this as json
response.status(200).send({
success: true,
voucher: {
name: results,
xxx: 10
}
})
})
Client
your client side can then be, assuming $ is jquery's post function
var body = {
code: code
}
$.post('http://localhost:8080/voucher', body).then(function(res) {
console.log(res)
console.log(res.data)
return res.data
})
I have an HTML page where a user can access a Web API 2 webservice to get some data. This HTML page is not part of the MVC application, but is a standalone HTML page, that can be on any web server or local OS.
Before the user can get the data, the user has to request a token with the following code:
function login()
{
self.result = '';
var loginData = {
grant_type: 'password',
username: document.getElementById("loginEmailTest").value,
password: document.getElementById("loginPasswordTest").value
};
$.ajax({
type: 'POST',
url: 'https://localhost/token/Token',
data: loginData
}).done(function (data) {
self.user = data.userName;
// Cache the access token in session storage.
sessionStorage.setItem(tokenKey, data.access_token);
}).fail(showError);
}
How can I prevent access to a group of HTML pages, such that the user has to have a valid token or logon details before a page is loaded?
Can javaScript be used successfully with a simple cookie or sessionStorage check?
yes.
requestHtml.php:
<?php
if(!isset($_POST['token'] || !is_valid_token($_POST['token'])){
header("HTTP/1.1 401 Unauthorized",true,401)
die("invalid token!");
}
$whitelist('foo.html','bar.html','baz.html');
if(!isset($_POST['html']) || !in_array($_POST['html'],$whitelist)){
header("HTTP/1.0 404 Not Found",true,404);
die("HTTP/1.0 404 Not Found");
}
readfile($_POST['html']);
and in the javascript,
function requestHtml(html){
var token=sessionStorage.getItem(tokenKey);
if(!token){
return false;//no token
}
var xhr=new XMLHttpRequest();
xhr.open("POST","requestHtml.php",false);
var fd=new FormData();
fd.append("token",token);
fd.append("html",html);
return xhr.send(fd);
}
My site is running on Node and using the Express framework.
My goal is to gather data from the Yahoo Placefinder api. It does not support JSONP, so I need to send my JQuery.getJSON request to my own proxy. My proxy would then send an http request to the Placefinder api, and echo the response.
If I were using php instead of Node, I would just make a new php file that includes a curl request to the placefinder api and echo the response.
But, I am using Node and I'm not sure where to start.
And, I'm using the Express framework.
My Questions are:
Where would the proxy fit within the Express framework? The public folder?
Where can I find some info on how to code a proxy in Node?
Will I need to modify the configuration of my Rackspace cloud (ubuntu) server in order for this to be possible?
See node-http-proxy. It should be better than implementing your own proxy.
Express lets you add middlewares as arguments when you do express.createServer(). Or, you can add them afterwards by using .use(proxy).
I don't think so.
To give an example (untested code):
var httpProxy = require('http-proxy'), express = require('express');
var yahooProxy = httpProxy.createServer(80, 'yahoo.com');
var app = express.createServer();
app.configure(function () {
app.use('/yahoo', yahooProxy);
});
...
Here's another example with 1.0.X that demonstrates header injection.
var express = require( 'express' );
var proxy = require( 'http-proxy' ).createProxyServer;
var app = express();
app.configure(function() {
// Inject some request headers here before we proxy...
app.use( function( req, res, next ) {
req.headers[ 'x-my-header' ] = 'blah blah';
next();
});
// Proxy based on path...
app.use( '/stack', proxy({ target: 'http://stackoverflow.com'} ).web );
app.use( '/yahoo', proxy({ target: 'http://yahoo.com'} ).web );
app.use( function( req, res ) {
res.send({ ok: false, message: 'Not much here.' })
});
}).listen( 3000 );
You can just add another route to your express app, perhaps at /api/yahoo/....
This view function will then make a call to the Yahoo API, probably using: http://nodejs.org/docs/v0.4.9/api/http.html#http.request, and then when that request finishes you simple return the result as JSON.
However, keep in mind that your proxy is public and that anyone can make requests through it. I would suggest some basic authorization. A generated value which you provide to the page making the request should work.
Using http-proxy 1.0 with express:
var httpProxy = require('http-proxy');
var apiProxy = httProxy.createProxyServer();
app.get("/api/*", function(req, res){
apiProxy.web(req, res, { target: 'http://google.com:80' });
});
Nowadays this seems to be the easiest solution to add a proxy to Express:
https://www.npmjs.org/package/proxy-middleware