React Native + Django DRF network error on POST - python

I'm developing a React Native app. As a backend I'm using DJango DRF. I'm trying to make POST request for creating a new element on backend, this is my code in React:
**API.JS**
const routes = {
accounts: {
get: () =>
requestHelper({
method: "get",
url: "accounts/",
}),
post: (data) =>
requestHelper({
data,
method: "post",
url: "accounts/",
}),
},
};
**API CALL**
const formData = new FormData();
const image = {
uri: data.image,
name: data.timestamp + ".jpg",
type: "image/jpeg",
};
_.map(data, (item, name) => {
formData.append(name, item);
});
formData.append("image", image);
await api.accounts
.post(formData)
.then((res) => {
console.log(res, "OK");
})
.catch((err) => {
console.log(err);
});
};
Te request is reaching backend and the new Account is being created on database (including the image). The problem is that,despite that Django is returning 200_OK, the api call is going to the catch statement, and this error appears on console:
Network Error
Stack trace: node_modules/axios/lib/core/createError.js:15:0 in
node_modules/axios/lib/adapters/xhr.js:81:4 in
dispatchXhrRequest
node_modules/event-target-shim/dist/event-target-shim.js:818:20 in
EventTarget.prototype.dispatchEvent
node_modules/react-native/Libraries/Network/XMLHttpRequest.js:575:10
in setReadyState
node_modules/react-native/Libraries/Network/XMLHttpRequest.js:389:6 in
__didCompleteResponse node_modules/react-native/Libraries/vendor/emitter/EventEmitter.js:189:10
in emit
node_modules/react-native/Libraries/BatchedBridge/MessageQueue.js:425:19
in __callFunction
node_modules/react-native/Libraries/BatchedBridge/MessageQueue.js:112:6
in __guard$argument_0
node_modules/react-native/Libraries/BatchedBridge/MessageQueue.js:373:10
in __guard
node_modules/react-native/Libraries/BatchedBridge/MessageQueue.js:111:4
in callFunctionReturnFlushedQueue [native code]:null in
callFunctionReturnFlushedQueue
I think is not an Image problem, because I've removed for testing and same error appears.

Usually, you get the Network Error when the REST API server can't be reached. Have you set the correct baseURL or proxy to the Django server? Django server is probably running on 8000 and React is running by default on 3000.
The fact that you see a request on the server-side is a little strange. It will suggest that there might be a bug/problem in the code that is used to process a successful response. Have you tried to remove that code? Yes, might sound strange, just remove the console.log(res, "OK"); and see what will happen?

Related

Getting Error 400 uploading file to Flask Rest

I am unable to track down this issue I am having attempting to send a FormData object (containing a file) to a Flask-RESTful application. On the ReactJS side i have the following code:
const updateAvatar = ({ target }) => {
if (target.value) {
let form = new FormData()
form.append("file", target.files[0])
fetch(`myurl/avatar`, {
credentials: "include",
method: "POST",
headers: { 'Content-Type':"application/x-www-form-urlencoded" },
body: form
})
.then(response => response.json())
.then(data => Do Something)
}
}
On the Flask side I have the following code:
def post(self,user):
if request.endpoint=="avatar":
print('I can see this message but I error out on the next line')
f=request.files["file"]
The f=request.files["file"] causes the server to return a 400 error. I thought this was straight forward but i'm a bit stuck here.
One other thing to mention: I am running in a local HTTPS environment using credentials.
Any help would be much appreciated.

How can I get the console output in Angular webpage?

I have a Django project which is using Angular as frontend. I have a button which on clicking is scanning the tables in the database. I have some print statements views.py file which is printing the scanned results constantly in the IDE console. I want that output in the webpage. I want that live printing of the console output in the frontend. Can any one know how i can achieve this?
You can achieve this by using server sent events. python can push these console logs to the frontend. Not a expert of python so giving a link below to how to send server side events from python to frontend
https://medium.com/code-zen/python-generator-and-html-server-sent-events-3cdf14140e56
In frontend you can listen to url exposed and as soon as server will push any message on this stream frontend can receive it and push it into component's array and can display over ui.
for frontend code, i am giving a minimal example below :-
import { Injectable, NgZone } from "#angular/core";
import { Observable } from "rxjs";
#Injectable({
providedIn: "root"
})
export class SseService {
constructor(private _zone: NgZone) {}
getServerSentEvent(url: string): Observable<any> {
return Observable.create(observer => {
const eventSource = this.getEventSource(url);
eventSource.onmessage = event => {
this._zone.run(() => {
observer.next(event);
});
};
eventSource.onerror = error => {
this._zone.run(() => {
observer.error(error);
});
};
});
}
private getEventSource(url: string): EventSource {
return new EventSource(url);
}
}
you can susbcribe to getServerSentEvent in above method and can continuously receive new messages, which is in your case your console logs.
You can try calling the following function with the information needed to be displayed.
addItem(val:any) {
let node = document.createElement("li")
let textnode = document.createTextNode(val)
node.appendChild(textnode)
document.getElementById("output").appendChild(node)
}
Make sure to have an element with the id="output".

AngularJS - http request with Basic Auth (connect to FreeNAS)

Im trying to connect to the REST API of FreeNAS (http://api.freenas.org/authentication.html) within my AngularJS app. The API uses basic authentication with username and password.
In python this is a very easy thing as there is only one line of code:
requests.get('http://freenas.mydomain/api/v1.0/account/bsdusers/',auth=('root', 'freenas'))
I tried to find something for AngularJS but stumbled only over excrutiating code, e.g. How do I get basic auth working in angularjs?
Is there anything available like this:
$http({
method: 'GET',
url: 'http://freenas.mydomain/api/v1.0/account/bsdusers/',
auth: ['username':'root', 'password':'pw']
}).then(function successCallback(response) {
// this callback will be called asynchronously
// when the response is available
}, function errorCallback(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
You need to create a function for encoding the user and password in Base64("username:password") and add Authorization header.
You can try encoding your username and password over here https://www.base64encode.org/ and see if it works. "root:freenas" being cm9vdDpmcmVlbmFz you can try the code below.
$http.defaults.headers.common['Authorization'] = 'Basic cm9vdDpmcmVlbmFz';
Once you get it working get implement the Base64 factory you posted ( How do I get basic auth working in angularjs? )
Hope it helps :)
You can try like this.
$http.defaults.headers.common = {"Access-Control-Request-Headers": "accept, origin, authorization"};
$http.defaults.headers.common['Authorization'] = 'Basic ' + Base64.encode('root' + ':' + 'freenas');
$http({
method: 'GET',
url: 'http://freenas.mydomain/api/v1.0/account/bsdusers/'
}).then(function successCallback(response) {
// this callback will be called asynchronously
// when the response is available
}, function errorCallback(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});

Implement Google+ Sign-In without Flask (on GAE)

I've got an app on Google App Engine for which I use the webapp2 authentication as described in this tutorial (thus Google Account API is not being used for user account management).
Therefore I'm using this Google tutorial to implement Google+ Sign-In. The front-end works fine, however I am having troubles with the callback. I would like to do this without Flask, since the only thing it seems to be used for is generating a response. The original code for the first part of the callback is:
if request.args.get('state', '') != session['state']:
response = make_response(json.dumps('Invalid state parameter.'), 401)
response.headers['Content-Type'] = 'application/json'
return response
To get rid of the Flask dependency, I rewrote this to:
if self.request.get('state') != self.session.get('state'):
msg = json.dumps('Invalid state parameter.')
self.response.headers["Content-Type"] = 'application/json'
self.response.set_status(401)
return self.response.out.write(msg)
The problem though, is that self.request.get('state') returns nothing. I'm guessing this is because I am not reading the response properly, however I don't know how to do it right.
The Javascript that launches the callback is:
function signInCallback(authResult) {
if (authResult['code']) {
// Send the code to the server
$.ajax({
type: 'POST',
url: '/signup/gauth',
contentType: 'application/octet-stream; charset=utf-8',
success: function(result) {
console.log(result),
processData: false,
data: authResult['code']
});
} else if (authResult['error']) {
// There was an error.
// Possible error codes:
// "access_denied" - User denied access to your app
// "immediate_failed" - Could not automatially log in the user
console.log('There was an error: ' + authResult['error']);
}
}

Calling a python function using dojo/request

Firstly, I'm very new to the world of web development, so sorry if this question is overly simple. I'm trying to use python to handle AJAX requests. From reading the documentation it seems as though Dojo/request should be able to do this form me, however I've not found any examples to help get this working.
Assuming I've got a Python file (myFuncs.py) with some functions that return JSON data that I want to get from the server. For this call I'm interested in a particular function inside this file:
def sayhello():
return simplejson.dumps({'message':'Hello from python world'})
What is not clear to me is how to call this function using Dojo/request. The documentation suggests something like this:
require(["dojo/dom", "dojo/request", "dojo/json", "dojo/domReady!"],
function(dom, request, JSON){
// Results will be displayed in resultDiv
var resultDiv = dom.byId("resultDiv");
// Request the JSON data from the server
request.get("../myFuncs.py", {
// Parse data from JSON to a JavaScript object
handleAs: "json"
}).then(function(data){
// Display the data sent from the server
resultDiv.innerHTML = data.message
},
function(error){
// Display the error returned
resultDiv.innerHTML = error;
});
}
);
Is this even close to what I'm trying to achieve? I don't understand how to specify which function to call inside myFuncs.py?
What you could also do is to create a small jsonrpc server and use dojo to do a ajax call to that server and get the json data....
for python side you can follow this
jsonrpclib
for dojo you could try something like this..
<script>
require(['dojox/rpc/Service','dojox/rpc/JsonRPC'],
function(Service,JsonRpc)
{
function refreshContent(){
var methodParams = {
envelope: "JSON-RPC-2.0",
transport: "POST",
target: "/jsonrpc",
contentType: "application/json-rpc",
services:{}
};
methodParams.services['myfunction'] = { parameters: [] };
service = new Service(methodParams);
function getjson(){
dojo.xhrGet({
url: "/jsonrpc",
load : function(){
var data_list = [];
service.myfunction().then(
function(data){
dojo.forEach(data, function(dat){
data_list.push(dat);
});
console.log(data_list)
},
function(error) {
console.log(error);
}
);
}
});
}
getjson();
}
refreshContent();
});
});
</script>
I've used this approach with django where i am not creating a different server for the rpc calls but using django's url link to forward the call to my function.. But you can always create a small rpc server to do the same..

Categories