I am following this tutorial to build a realtime application using Django and Socket.io (node js). I am building this inside a vagrant box, and has configured the vagrant machine in my host file. Now since the tutorial is an old post, I got many errors. However after fixing some deprecated codes, this is what it looks like.
chat.js:
var server = require('http').createServer().listen(4000);
var io = require('socket.io').listen(server, {
'authorization': function(data, accept) {
if (data.headers.cookie) {
data.cookie = cookie_reader.parse(data.headers.cookie);
return accept(null, true);
}
return accept('error', false);
}
});
var cookie_reader = require('cookie');
var querystring = require('querystring');
var redis = require('redis');
var sub = redis.createClient();
sub.subscribe('chat');
io.on('connection', function (socket) {
sub.on('message', function(channel, message){
socket.send(message);
});
socket.on('send_message', function (message) {
values = querystring.stringify({
comment: message,
sessionid: socket.handshake.cookie['sessionid'],
});
var options = {
host: 'localhost',
port: 80,
path: '/node_api',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': values.length
}
};
//Send message to Django server
var req = http.get(options, function(res){
res.setEncoding('utf8');
//Print out error message
res.on('data', function(message){
if(message != 'Everything worked :)'){
console.log('Message: ' + message);
}
});
});
req.write(values);
req.end();
});
});
index.html:
<head>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js" type="text/javascript"></script>
<script src="{% static "js/socket.io.js" %}"></script>
<script>
$(document).ready(function () {
var socket = io('http://localhost:4000');
socket.on('connect', function () {
console.log("connect");
});
...
...
...
</script>
But now when I load the page I am stuck with this error
GET http://localhost:4000/socket.io/?EIO=3&transport=polling&t=LA7JSiV net::ERR_CONNECTION_REFUSED
When in the index.html I change this
var socket = io('http://localhost:4000');
to this
var socket = io();
I get this error
GET http://vagrant-box.com/socket.io/?EIO=3&transport=polling&t=LA7NH61 404 (NOT FOUND)
What am I doing wrong? Please help me solve this problem. Your help will be very much appreciated. Thank you.
First notice that you can't serve the socket.io js from django, socket.io has to serve it's own js files because it does some clever magic to determine the files it has to send.
Change
<script src="{% static "js/socket.io.js" %}"></script>
to
<script type="text/javascript" src="http://localhost:4000/socket.io/socket.io.js"></script>
(you will have to change these urls on production)
after that you must let socket.io know the exact schema, host and port to connect to the node.js server or you will get a 404 as socket will try to connect to the port your django server is listening at.
var socket = io('http://localhost:4000');
Related
I am trying to send post data to a django Restful API using vuejs. here is the code I have so far:
<script>
import axios from 'axios'
import VueCookies from 'vue-cookies'
//3RD ATTEMPT
VueCookies.set("csrftoken","00000000000000000000000000000000");
// # is an alias to /src
export default {
name: "Signup",
components: {},
data: () => {
},
methods: {
sendData(){
// 2ND ATTEMPT
// $cookies.set("csrftoken", "00000000000000000000000000000000");
axios({
method: 'post', //you can set what request you want to be
url: 'https://localhost:8000/indy/signup/',
data: {
csrfmiddlewaretoken: "00000000000000000000000000000000",
first_name: "wade",
last_name: "king",
email: "wade%40mail.com",
password1: "05470a5bfe",
password2: "05470a5bfe"
},
// 1ST ATTEMPT
// headers: {
// Cookie: "csrftoken= 00000000000000000000000000000000"
// },
withCredentials: true
})
}
}
</script>
I have a button which executes the sendData() method on a click. The code uses the axios library to send a post request to the django API running on http://localhost:800/indy/signup/
The problem with just sending a post request to the API is that it will get blocked in order to prevent Cross Site Response Forgery (CSRF), I dont quite understand CSRF but I know if the csrftoken is set as a cookie and has the same value as the csrfmiddlewaretoken then the post should go through to the API.
You can see my attempts to set the cookie in the code I provided
1ST ATTEMPT)
headers: {
Cookie: "csrftoken= 00000000000000000000000000000000"
},
Here I'm trying to set the cookie directly in the header. When I click send I get an error in my browser console saying refused to set unsafe header "Cookie"
2ND ATTEMPT)
$cookies.set("csrftoken", "00000000000000000000000000000000");
Here I'm trying to set the cookie using the vue-cookies module. When i click send I get the following error, net::ERR_SSL_PROTOCOL_ERROR
3RD ATTEMPT)
VueCookies.set("csrftoken","00000000000000000000000000000000");
Here I'm trying to set a global cookie using the vue-cookies module. When I click send I get the same error as attempt 2
IMPORTANT:
However when I send post data to the API from my terminal using the following curl command, it works perfectly
curl -s -D - -o /dev/null \
-H 'Cookie: csrftoken= 00000000000000000000000000000000' \
--data 'csrfmiddlewaretoken=00000000000000000000000000000000&first_name=wade&last_name=king&email=wade%40mail.com&password1=05470a5bfe&password2=05470a5bfe' \
http://localhost:8000/indy/signup/
my main question is How can I replicate this curl request using vuejs? I've looked all over on line and none of the tutorials deal with setting cookies.
I posted this question some time ago, I have managed to work around it by running the vue frontend on the same network as the django backend. Follow this tutorial for instructions: integrating vuejs and django
Once I had the application set up I was able to set the cookies much more cleanly using :
axios.defaults.xsrfCookieName = 'csrftoken'
axios.defaults.xsrfHeaderName = "X-CSRFTOKEN"
Here is my login page for example
<template>
<div class = "container">
<h2>Sign In</h2>
<b-form v-on:submit.prevent="submit()">
<b-form-group id="signin" label="">
<!-- dynamic error message -->
<p class="loginErr" v-if="logErr">Incorrect Username or Password</p>
<b-form-input
id="signin-email"
v-model="username"
placeholder="Email"
required
></b-form-input>
<b-form-input
id="signin-password"
v-model="password"
placeholder="Password"
required
type="password"
></b-form-input>
</b-form-group>
<b-button v-if="!loading" type="submit" variant="primary">Submit</b-button>
<b-spinner v-if="loading"></b-spinner>
</b-form>
</div>
</template>
<script>
import axios from 'axios'
import Vue from 'vue'
export default {
data: ()=>{
return{
loading: false,
logErr: false,
username:'',
password:'',
next: '%2Findy%2Fprofile%2F'
}
},
created: function(){
},
methods: {
submit(){
var vm = this;
vm.loading = true;
var dataStr = 'username='+vm.username+'&password='+vm.password
//set the csrf tokens so django doesn't get fussy when we post
axios.defaults.xsrfCookieName = 'csrftoken'
axios.defaults.xsrfHeaderName = "X-CSRFTOKEN"
axios.post('http://localhost:8000/api/signin/', dataStr)
.then(function (response) {
vm.loading = false;
//determine if indy accepts the login request
var res = response.data
console.log(response.data)
if(!res.login){
vm.logErr = true;
}else{
vm.redirect('home');
}
})
.catch(function (error) {
//currentObj.output = error;
});
},
redirect(path) {
this.$router.push('/' + path);
}
}
}
</script>
<style>
.loginErr{
color: orange;
}
</style>
I would like to inject a custom http service in my embedded task form application.
Herewith is the code snippet:
<script cam-script type="text/form-script">
inject([ '$scope', '$http', function($scope, $http) {
camForm.on('form-loaded', function() {
// Custom service call
$http.get('http://localhost:8888/books/1').then(function(response){
alert(JSON.stringify(response.data));
});
});
}]);
When the form loads the http://localhost:8888/books/1 isn't invoked and I don't know why.
For anybody else running into the same issue here is the code snippet that made debugging a bit easier:
<script cam-script type="text/form-script">
debugger;
inject([ '$scope', '$http', function($scope, $http) {
camForm.on('form-loaded', function() {
$http({
method: 'GET',
url: 'http://localhost:8888/books/1'
}).then(
function successCallback(response)
{
alert('SUCCESS :-) ' + angular.toJson(response.data));
$scope.data = response.data
},
function errorCallback(response) {
alert('FAILED :-( ' + response.status);
});
});
}]);
</script>
As for the solution, I had to enable CORS on the server that was receiving the request. See https://spring.io/guides/gs/rest-service-cors/
First, a facebook user is logged client-side with using Facebook JS SDK.
FB.init() is called with the following parameters:
{
version : 'v2.0',
appId: '...',
status : true,
cookie : true,
xfbml : false
}
Then, in PHP, a session is created:
$session = (new FacebookJavaScriptLoginHelper())->getSession();
Once FB API calls have been made from PHP, I still can continue calling FB API from withing js.
But as soon as my page sends a new command to the server instructing it to make an FB API call, it doesn't work the second time, and the FB API says:
An access token is required to request this resource.
Obviously, this is called one more time and after that it stops working:
$session = (new FacebookJavaScriptLoginHelper())->getSession();
If the user updates the page in his browser, the next call from the server will work again. What I want instead is to keep querying FB API from both the server and the browser simultaneously without reloading the page.
It is out of date, but maybe will help someone
<?php
//some code here - requires and uses
FacebookSession::setDefaultApplication($SETTINGS['fbappid'], $SETTINGS['fbsecret']);
$helper = new FacebookJavaScriptLoginHelper();
$session;
try {
$session = $helper->getSession();
} catch(FacebookRequestException $ex) {
//
} catch(\Exception $ex) {
//
}
?>
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<script>
window.fbAsyncInit = function() {
FB.init({
appId : '<?php echo $SETTINGS['fbappid'] ?>',
xfbml : true,
version : 'v2.0',
status : true,
cookie : true
});
FB.getLoginStatus(function(response) {
if (response.status === 'connected') {
var uid = response.authResponse.userID;
var accessToken = response.authResponse.accessToken;
FB.login(function () {
FB.api('/me', {
fields: 'id'
}, function (response) {
console.log(response);
});
}, {
scope: 'publish_actions'
});
} else if (response.status === 'not_authorized') {
} else {
}
});
};
(function(d, s, id){
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {return;}
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/en_US/sdk.js";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
</script>
<div id="fb-root"></div>
<?php
//here url to go to my app
echo "<a href='...'>Sign in to Facebook application</a>";
if ($session) {
echo "<br/>logged in";
}
?>
</body>
</html>
Note that login comes after second access to page if cookies were not set. So ajax request is needed to check properly.
I'm trying to load some posts asynchronously via the javascript SDK from facebook. I'm loading the javascript files at the bottom of the page:
<html>
<head>.....</head>
<body>
.....
.....
.....
<div id="fb-root"></div>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script type="text/javascript" src="/res/jquery.stp.js" charset="utf-8"></script>
</body></html>
In jquery.stp.js I'm loading these things in this order:
- the javascript sdk
- some jquery-things
- a function loadFBPosts()
- fb.init()
The file:
var isLoaded = false;
(function(d, debug){
var js, id = 'facebook-jssdk', ref = d.getElementsByTagName('script')[0];
if (d.getElementById(id)) {return;}
js = d.createElement('script'); js.id = id; js.async = true;
js.src = "//connect.facebook.net/en_US/all" + (debug ? "/debug" : "") + ".js";
ref.parentNode.insertBefore(js, ref);
}(document, /*debug*/ false));
$(function(){
//some jquery event things
})
function loadFBPosts(fbPageId) {
// Facebook call
if(isLoaded) {
//do some things with the FB.api()
//and catch errors...
}else{
//api not loaded...
}
}
window.fbAsyncInit = function() {
// init the FB JS SDK
FB.init({
appId : 'xxxxx',
channelUrl : '//lab.example.com/channel.php',
status : true,
cookie : true,
xfbml : true
});
isLoaded = true;
laadFBPosts(); // here after FB.init is initialized call the function.
};
Questions
Now something odd happens. If I run this page an error pops up: "An access token is required to request this resource" with error-code 104.
But if I click a link on the page <a href='javascript:loadFBPosts()'>click</a> then the function gets execute like it should.
How is this possible? The resources I try to get with the FB.api() are from public facebook pages. eg FB.api('/218818688131271/posts?limit=5') so I shouldn't need an access token. Right?
If I do need an acces token: how do I obtain one if I don't want to bother every visitor with a login screen; because it's just a displaying of public info....
The only thing I want to do is to display the last 5 posts off my page and the upcoming events.
SO I am trying to have my web site publish info to a user's facebook page. Where I am now is that I placed the following code (as instructed by another stackoverflow contributor), which is getting executed however the alert with "error occurred" comes up. Do I need to request the publish_stream permission as well? If so, I cannot figure out how to add that to my code. Sorry, I'm not much of a scripter and I have very limited knowledge on doing any integration into facebook. My ultimate goal is to be able to post information to a users facebook page on their behalf (this won't be done without their permission). Any help would be much appreciated:
<div id="fb-root"></div>
<script>
window.fbAsyncInit = function() {
FB.init({
appId : 'XXXXXXXXXXXXXXXXXXXX', // App ID
channelUrl : '//www.XXXXXXXXXXXXXX.com/channel.html', // Channel File
status : true, // check login status
cookie : true, // enable cookies to allow the server to access the session
xfbml : true, // parse XFBML
oauth : true
});
});
// Additional initialization code here
};
// Load the SDK Asynchronously
(function(d){
var js, id = 'facebook-jssdk', ref = d.getElementsByTagName('script')[0];
if (d.getElementById(id)) {return;}
js = d.createElement('script'); js.id = id; js.async = true;
js.src = "//connect.facebook.net/en_US/all.js";
ref.parentNode.insertBefore(js, ref);
}(document));
</script>
<SCRIPT language="JavaScript">
FB.login(function(response) {
if (response.authResponse) {
console.log('Welcome! Fetching your information.... ');
FB.api('/me', function(response) {
console.log('Good to see you, ' + response.name + '.');
});
} else {
console.log('User cancelled login or did not fully authorize.');
}
});
</SCRIPT>
<SCRIPT language="JavaScript">
var body = 'Reading JS SDK documentation';
FB.api('/me/feed', 'post', { message: body }, function(response) {
if (!response || response.error) {
alert('Error occured');
} else {
alert('Post ID: ' + response.id);
}
})
</SCRIPT>
Why don't you expand the error handling a little bit?
alert("Error occured: " + response.error.message);
And did you check the console log for errors? Maybe authentication didn't work.