Accessing request data object - django

I am sending the following post Data to django Rest API
Request URL: http://localhost:8000/polls/
Request Method: POST
Status Code: 200 OK
Remote Address: 127.0.0.1:8000
Referrer Policy: no-referrer-when-downgrade
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://localhost:8100
Content-Length: 90
Content-Type: text/html; charset=utf-8
Date: Mon, 18 Jun 2018 11:01:54 GMT
Server: WSGIServer/0.2 CPython/3.6.5
Vary: Origin
X-Frame-Options: SAMEORIGIN
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: keep-alive
Content-Length: 83
content-type: text/plain
Host: localhost:8000
Origin: http://localhost:8100
Referer: http://localhost:8100/
User-Agent: Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.170 Mobile Safari/537.36
0:
{id: "1", username: "admin", password: "admin", user_group_id: "1", status: "1"}
The sent here will first be authenticated against the one saved in the database. I am trying to access this data but failing to do so .
When I process the data using json parse
case 1.
def dunction(request)
data = json.loads(request.body.decode("utf-8"))
vak=data
return HttpResponse(vak)
Then the following response is received
{'id': '1', 'username': 'admin', 'password': 'admin', 'user_group_id': '1', 'status': '1'}
case 2.
When manipulating the same code
data = json.loads(request.body.decode("utf-8"))
vak=data[0]
return HttpResponse(vak)
received response
idusernamepassworduser_group_idstatus
Case 3.
def dunction(request):
data = json.loads(request.body.decode("utf-8"))
vak=data.username
return HttpResponse(vak)
throws error 'list' object has no attribute 'username'
FYI,
Here I am trying to create a custom authentication function which authenticates the userData and then sends data back to the server.
'DEFAULT_AUTHENTICATION_CLASSES':
'polls.authentication.UserAuthentication',

HttpResponse takes an iterable. You are passing it various things that are in fact iterable: in the first case, a list, so it prints the (only) entry in that list, which is a dictionary; in the second case, you pass it a dict, so it iterates through the dict which gives the keys only. In the third case, for some reason you try and use object notation to access a key of a dict which is inside a list, which won't work at all.
I'm not sure what your actual question is, but if you do want to access the username you would need data[0]['username'].
Note though that the point of DRF is to abstract away a lot of this stuff; you should use the built-in functionality rather than doing any of this.

Use request.data to get the data for processing. return message along with HTTP status code like below
def dunction(request):
username=request.data['username']
password=request.data['password']
group_id=request.data['user_group_id']
status=request.data['status']
return Response({"status":"success"}, status=status.HTTP_200_OK)

Related

Browser doesn't store cookies

I'm sending Cookie from Laravel application (http://backend.local) to Vue SPA (http://frontend.local:8080):
Laravel side (dummy route)
//api routes
Route::post('login', function () {
setcookie("name", 'value', time()+3600, "/", ".local");
return response('ok');
});
Vue side
axios.post('//backend.local/api/login')
.then(response => {
console.log(response)
}).catch(error => {
})
Response Headers:
HTTP/1.1 200 OK
Date: Mon, 21 May 2018 09:42:35 GMT
Server: Apache
Set-Cookie: name=value; expires=Mon, 21-May-2018 10:42:36 GMT; Max-Age=3600; path=/; domain=.local
Cache-Control: no-cache, private
Access-Control-Allow-Origin: http://frontend.local:8080
Vary: Origin
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 59
Content-Length: 2
Keep-Alive: timeout=10, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8
But there is no Cookies in broswer storage (Application tab in Developers Console).
What's wrong?
UPDATE: I think the problem is that there is port number in http://frontend.local:8080. Can I remove port number from url?
Original Answer
The browser will automatically reject any domain which doesn't have two parts to it. So using .local is not considered a domain at all. You need to two levels at least. Consider the below flask app I created for demoing the same
from flask import Flask, request, make_response
app = Flask(__name__)
#app.route("/")
def index():
resp = make_response()
resp.set_cookie('value1', ".frontend.local", domain=".frontend.local")
resp.set_cookie('value2', "frontend.local", domain="frontend.local")
resp.set_cookie('value3', ".local", domain=".local")
return resp
app.run(debug=True)
Now testing this through curl
$ curl -v frontend.local:5000
* Rebuilt URL to: frontend.local:5000/
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to frontend.local (127.0.0.1) port 5000 (#0)
> GET / HTTP/1.1
> Host: frontend.local:5000
> User-Agent: curl/7.54.0
> Accept: */*
>
* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Content-Type: text/html; charset=utf-8
< Set-Cookie: value1=.frontend.local; Domain=.frontend.local; Path=/
< Set-Cookie: value2=frontend.local; Domain=frontend.local; Path=/
< Set-Cookie: value3=.local; Domain=.local; Path=/
< Content-Length: 0
< Server: Werkzeug/0.14.1 Python/3.6.5
< Date: Tue, 29 May 2018 12:58:20 GMT
<
* Closing connection 0
When you navigate this in browser, you can see that the cookie with Domain=.local gets discarded but rest 2 remains
And later you can see that both the cookies have been sent to the reload of the same page
Update 1: 30th May 2018
Since you are using 2 different domains, you should use frontend.local.com and backend.local.com and the cookies should be returned with domain as .local.com, so that backend and frontend works as a subdomain of local.com. Then frontend.local.com gets the cookies set by backend.local.com through domain sharing as the cookie domain is set to .local.com
Since this is a CORS call, you will need to set setCredentials to true. This is a standard behavior: Standard CORS requests do not send or set any cookies by default.
The withCredentials property will include any cookies from the other domain in the request and also set any cookies from other domain.
So your Vue.js code will be:
axios.defaults.withCredentials = true
axios({
method: 'POST',
url: '//backend.local/api/login',
// THIS IS IMPORTANT
withCredentials: true
})
.then(response => {
console.log(response)
}).catch(error => {})
[Edit]: Read more about CORS at HTML Rocks.
Please let me know if it doesn't help.

How to enable CORS in python

Let me start this with, I do not know python, I've had maybe 1 day going through the python tutorials. The situation is this. I have an angular app that has a python app hosted with Apache on a vm in an iframe. I didn't write the python app, but another developer wrote me an endpoint where I am supposed to be able to post from my angular app.
The developer who made the python endpoint is saying that there is something wrong with my request but I am fairly certain there isn't anything wrong. I am almost 100% certain that the problem is that there are no CORS headers in the response and/or the response is not set up to respond to the OPTIONS method. Below is the entirety of the python endpoint:
import os, site, inspect
site.addsitedir(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))+"/../")
import json
from datetime import datetime
import pymongo
from Config import Config
def application(environ, start_response):
response = environ['wsgi.input'].read(int(environ['CONTENT_LENGTH']))
if response:
json_response = json.loads(response)
document = {
'payment_id': json_response['payment_id'],
'log': json_response['log'],
'login_id': json_response['login_id'],
'browser': environ.get('HTTP_USER_AGENT', None),
'ip_address': environ.get('REMOTE_ADDR', None),
'created_at': datetime.utcnow(),
}
client = pymongo.MongoClient(Config.getValue('MongoServer'))
db = client.updatepromise
db.PaymentLogs.insert(document)
start_response('200 OK', [('Content-Type', 'application/json')
return '{"success": true}'
start_response('400 Bad Request', [('Content-Type', 'application/json')])
return '{"success": false}'
I have attempted the following to make this work: I added to both start_response functions more headers so the code looks like this now:
start_response('201 OK', [('Content-Type', 'application/json',
('Access-Control-Allow-Headers','authorization'),
('Access-Control-Allow-Methods','HEAD, GET, POST, PUT, PATCH, DELETE'),
('Access-Control-Allow-Origin','*'),
('Access-Control-Max-Age','600'))])
Not: I did this both with the 200 and the 400 response at first, and saw no change at all in the response, then just for the heck of it, I decided to change the 200 to a 201, this also did not come through on the response so I suspect this code isn't even getting run for some reason.
Please help, python newb here.
Addendum, i figured this would help, here is what the Headers look like in the response:
General:
Request URL: http://rpc.local/api/payment_log_api.py
Request Method: OPTIONS
Status Code: 200 OK
Remote Address: 10.1.20.233:80
Referrer Policy: no-referrer-when-downgrade
Response Headers:
Allow: GET,HEAD,POST,OPTIONS
Connection: Keep-Alive
Content-Length: 0
Content-Type: text/x-python
Date: Fri, 27 Apr 2018 15:18:55 GMT
Keep-Alive: timeout=5, max=100
Server: Apache/2.4.18 (Ubuntu)
Request Headers:
Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Access-Control-Request-Headers: authorization,content-type
Access-Control-Request-Method: POST
Connection: keep-alive
Host: rpc.local
Origin: http://10.1.20.61:4200
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36
Here it is. Just add this to the application right at the beginning:
def application(environ, start_response):
if environ['REQUEST_METHOD'] == 'OPTIONS':
start_response(
'200 OK',
[
('Content-Type', 'application/json'),
('Access-Control-Allow-Origin', '*'),
('Access-Control-Allow-Headers', 'Authorization, Content-Type'),
('Access-Control-Allow-Methods', 'POST'),
]
)
return ''
For Python with CGI, I found this to work:
print '''Access-Control-Allow-Origin: *\r\n''',
print '''Content-Type: text/html\r\n'''
Don't forget to enable CORS on the other side as well, e.g., JavaScript jQuery:
$.ajax({ url: URL,
type: "GET",
crossDomain: true,
dataType: "text", etc, etc

Empty Body in Vapor Client GET Response

I'm trying to connect to
Bamboo HR's API, and I've managed to make this work with curl and Swift Foundation's URLRequest/URLSession (as well as an older Express node.js app).
However, when trying to utilize Vapor's client with the .get() method, I'm getting a successful 200 response from BambooHR - but the response's .body is empty.
Here's the code snippet:
key and {myDomain} are placeholders in the example
let encodedKey = "\(key):x".utf8.base64String
let directoryRootUrl = "https://api.bamboohr.com/api/gateway.php/{myDomain}/v1/employees/directory"
let response = try drop.client.get(
directoryRootURL,
headers: [
"Accept": "application/json",
"Authorization": "Basic \(encodedKey)",
"Host": "api.bamboohr.com"
])
When I do print(response), this is what's displayed:
Response
- HTTP/1.0 200 OK
- Headers:
Connection: close
Vary: User-Agent
Server: Apache
Content-Security-Policy: {...}
Date: Mon, 16 Jan 2017 00:26:31 GMT
Content-Type: application/json
X-Content-Type-Options: nosniff
- Body:
I'm wondering if I'm doing anything wrong with Vapor, or if it's a bug.
Like tobygriffin suggested, setting:
drop.client = FoundationClient.self
after creating the Droplet worked.

HTTP/1.1 401 Unauthorized in Response Headers in Load runner for GET Requests

I am new to Load runner , Am facing am issue while play back of the script
LR 12.50
O.S Windows 7 SP2
Protocol is Mobile HTTP/HTML
Recording mode is Proxy
Let me explain my scenario
While executing following function:
web_custom_request("authenticate",
"URL=https://ws-xx.xxx.com/tcs/rest/authenticate?include=user,company",
"Method=POST",
"Resource=0",
"RecContentType=application/json",
"Referer=",
"Snapshot=t1.inf",
"Mode=HTTP",
"EncType=application/json",
"Body={\"password\":\"xxx\",\"username\":\"xxx\",\"version\":\"1.0.40\"}",
LAST);
For the above POST method , am getting response as below
HTTP/1.1 200 OK\r\n
Date: Tue, 13 Oct 2015 19:19:21 GMT\r\n
Server: Apache-Coyote/1.1\r\n
Content-Type: application/json\r\n
Set-Cookie: dtCookie=DBE9311E44E5C47902702DC762030583|TXlBcHB8MQ; Path=/;
Domain=.xxx.com\r\n
Connection: close\r\n
Transfer-Encoding: chunked\r\n
Which is fine ,Now the second custom request is shown below
web_custom_request("profiles",
"URL=https://ws-test.xxx.com/tcs/rest/profiles",
"Method=GET",
"Resource=1",
"RecContentType=application/json",
"Referer=",
"Snapshot=t2.inf",
LAST);
For the above GET requests in the replay logs am getting:
401 unauthorized error.
GET /tcs/rest/profiles HTTP/1.1\r\n
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT)\r\n
Accept: */*\r\n
Connection: Keep-Alive\r\n
Host: ws-test.xxx.com\r\n
Cookie: dtCookie=DBE9311E44E5C47902702DC762030583|TXlBcHB8MQ\r\n
\r\n
t=5921ms: 172-byte response headers for "https://ws-test.xxx.com/tcs/rest/profiles" (RelFrameId=1, Internal ID=2)
HTTP/1.1 401 Unauthorized\r\n
Date: Tue, 13 Oct 2015 19:19:22 GMT\r\n
Server: Apache-Coyote/1.1\r\n
Content-Type: application/json\r\n
Connection: close\r\n
Transfer-Encoding: chunked\r\n
\r\n
t=5922ms: 4-byte chunked response overhead for "https://ws-test.xxx.com/tcs/rest/profiles" (RelFrameId=1, Internal ID=2)
8b\r\n
t=5923ms: 139-byte chunked response body for "https://ws-test.xxx.com/tcs/rest/profiles" (RelFrameId=1, Internal ID=2)
{"errors":[{"message":"Authentication required to access endpoint","status":"401","code":"
NotAuthenticated","header":"Not Authenticated"}]}
I refereed this link.
My understanding from the above custom request , login is success but the next
subsequent requests are getting failed.
I have used web_cleanup_cookies() function but didn't solve the issue .
I tried to capture the Cookie ID using the below function
web_reg_save_param("COOKIE_ID",
"LR= Cookie: dtCookie=" ,
"RB= |TXlBcHB8MQ\r\n",
"Ord=All",
"RelFrameId=1",
"Search=All",
LAST);
web_add_header("Cookie",lr_eval_string("{COOKIE_ID}"));
Now question is where to place parameter "COOKIE_ID" in my script while there is
no value in script for COOKIE_ID?
How to handle this issue ? Can anybody please help me .
Please add below headers to the script
web_set_sockets_option("SSL_VERSION","TLS");
web_set_user("username", "password", "domain:portno" );
web_set_sockets_option("INITIAL_BASIC_AUTH","1");
In Vugen, Select snapshot view and compare both record and replay requests, suspecting there might be a missing of header in replay request.
If cookie is the only thing changing you can add it by using web_add_cookie function.

Tastypie not returning URI with UUID when UUIDField is primary key

I'm using Django and tastypie to develop a REST API, with a primary key that is a UUIDField from django_extensions. However, making the primary key a UUID isn't playing nicely with tastypie: when I create a resource with POST, the URI it returns is an int, not the UUID, and the provided URI is then unusable since the rest of the API expects the UUID to access a resource.
I think this is because the UUIDField only replaces the value in the UUIDField in Django's pre_save, and tastypie is returning the headers before that happens.
I tried writing a custom get_resource_uri for LocationResource, but the object passed into the function doesn't have a UUID yet (just the normal auto-incrementing integer primary key).
How can I get tastypie to return the correct UUID for a resource? Is there a better way of making a pk a UUID that tastypie will like better?
The model:
from django.db import models
from django_extensions.db.fields import UUIDField
class Location(models.Model):
""" Stores information about a location. """
id = UUIDField(primary_key=True)
path = models.TextField()
def __unicode__(self):
return "{uuid}: {path}".format(uuid=self.id, path=self.path)
The tastypie ModelResource (I'm still developing locally so authentication and authorization aren't set up properly yet):
class LocationResource(ModelResource):
class Meta:
queryset = Location.objects.all()
authentication = Authentication()
authorization = Authorization()
What I'm seeing (JSON formatted for readability):
$ curl --dump-header - -H "Content-Type: application/json" -X POST --data '{"path": "/path/to/directory/"}' http://localhost:8000/api/v1/location/
HTTP/1.0 201 CREATED
Date: Tue, 11 Jun 2013 19:59:07 GMT
Server: WSGIServer/0.1 Python/2.7.3
Vary: Accept
X-Frame-Options: SAMEORIGIN
Content-Type: text/html; charset=utf-8
Location: http://localhost:8000/api/v1/location/1/
$ curl --dump-header - -H "Content-Type: application/json" -X GET http://localhost:8000/api/v1/location/1/
HTTP/1.0 404 NOT FOUND
Date: Tue, 11 Jun 2013 19:59:27 GMT
Server: WSGIServer/0.1 Python/2.7.3
Vary: Accept
X-Frame-Options: SAMEORIGIN
Content-Type: text/html; charset=utf-8
$ curl --dump-header - -H "Content-Type: application/json" -X GET http://localhost:8000/api/v1/location/
HTTP/1.0 200 OK
Date: Tue, 11 Jun 2013 19:59:32 GMT
Server: WSGIServer/0.1 Python/2.7.3
Vary: Accept
X-Frame-Options: SAMEORIGIN
Content-Type: application/json
Cache-Control: no-cache
{"meta":
{"limit": 20, "next": null, "offset": 0, "previous": null, "total_count": 1},
"objects": [
{"id": "5fe23dd4-d2d1-11e2-8566-94de802aa978",
"path": "/path/to/directory/",
"resource_uri": "/api/v1/location/5fe23dd4-d2d1-11e2-8566-94de802aa978/"
}
]
}
From my experience, I wouldn't try use UUID with django (as a primary key that is). Perhaps some cleverer people have gotten it to work, but I've spent a few hours trying to get uuids working nicely, but its a real headache. By default django expects primary keys to be integers, and most django extensions make the same presumption.
Tastypie uses django's core resolver to generate the location, so the problem really isn't localised to tastypie. If you want UUIDs to work, you'd probably need to fork django and make your own changes, which is definitely not recommended.
At the end of the day, not having your uuid in your URI shouldn't actually matter too much. the idea of a URI is that its independent of model record, ie a uri doesn't have to contain the primary key of the model. A URI is in itself a unique identifier to a resource (read object), and so it shouldn't be a big concern to you what it looks like.