backbone.js fetch is not updating the model - api

I have read other posts here and it looks like most of the time this boils down to fetch being async. I don't think that is my problem because 1. I test the results in the success callback of fetch and 2. I can console.log(model.toJSON()) in the js console later and it still is not updated
Notes: I am getting a good json response from the API and I can get the data by putting 'parse' in my model declaration like so
parse: function(data){
alert(data.screenname);
}
Here is my code, why is the model not being updated with the fetch call
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
<script src="vendor/components/underscore/underscore-min.js"></script>
<script src="vendor/components/backbone/backbone-min.js"></script>
</head>
<body>
Hello
<script>
$.ajaxSetup({
beforeSend: function(xhr){
xhr.setRequestHeader("Authorization", "Basic " + window.btoa("username" + ":" + "password"));
}
});
var User=Backbone.Model.extend({
parse: function(data){
alert(data.screenname);
},
urlRoot: 'http://api.myapi.com/user'
});
var user=new User({id:'1'});
user.fetch({
success: function(collection, response, options){
console.log(response);
console.log(user.toJSON());
}
});
</script>
</body>
</html>
When I log response, it show a good json coming back, but user.toJSON just shows the id as 1.
I can use parse in the model declaration to manually assign each value in the model from the response, but that seems like a dumb way to do it. I was under the impression that fetch() was supposed to populate the model with the result from the server.
**UPDATED**
Here is the response I get back from the server
{"id":1,"email":"test#email.com","password":"pass","screenname":"myname","id_zipcode":1,"id_city":1,"date_created":"2014-12-25 12:12:12"}
Here are the response headers from my api
HTTP/1.1 200 OK
Date: Tue, 04 Feb 2014 18:31:41 GMT
Server: Apache/2.2.24 (Unix) DAV/2 PHP/5.5.6 mod_ssl/2.2.24 OpenSSL/0.9.8y
X-Powered-By: PHP/5.5.6
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Authorization, Origin, X-Requested-With, Content-Type, Accept
Set-Cookie: PHPSESSID=pj1hm0c2ubgaerht3i5losga4; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Content-Length: 139
Keep-Alive: timeout=5, max=99
Connection: Keep-Alive
Content-Type: application/json; charset=utf-8

You have overridden your parse() method to effectively do nothing. It should return all the attributes to set on your model; you have not returned anything, hence, nothing was being set on the model.
It should look like this.
var User=Backbone.Model.extend({
parse: function(data){
alert(data.screenname);
return data; //all attributes in data will be set on the model
},
urlRoot: 'http://api.myapi.com/user'
});

Related

Box api call returning 403 forbidden error in Vue but the same URL working in postman

I have a developer token for box and the box app all set up. when I use Postman I get the data that I am looking for returned. I have looked at the headers that Postman is sending and have provided the same in my code.
axios({
async: true,
crossDomain: true,
url: 'https://api.box.com/2.0/files/<File ID>/',
method: 'GET',
headers: {
'Postman-Token': '<Postman Token>',
'cache-control': 'no-cache',
Authorization: 'Bearer <Developer Token>',
Accept: '*/*',
},
}).then((res) => {
console.log(res);
}).catch(console.error);
This returns a 403 in the browser.
This is the Response Headers from Postman:
Date:"Wed, 03 Apr 2019 06:04:45 GMT"
Content-Type:"application/json"
Transfer-Encoding:"chunked"
Connection:"keep-alive"
Strict-Transport-Security:"max-age=31536000"
Cache-Control:"no-cache, no-store"
ETag:""0""
Content-Encoding:"gzip"
Vary:"Accept-Encoding"
BOX-REQUEST-ID:"<BOX-REQUEST-ID>"
Age:"0"
Response Headers from bowser
Access-Control-Allow-Origin: *
Age: 0
BOX-REQUEST-ID: <BOX-REQUEST-ID>
Cache-Control: no-cache, no-store
Connection: keep-alive
Content-Encoding: gzip
Content-Type: application/json
Date: Wed, 03 Apr 2019 06:36:01 GMT
Strict-Transport-Security: max-age=31536000
Transfer-Encoding: chunked
Vary: Origin,Accept-Encoding
Error in browser dev tools
GET https://api.box.com/2.0/files/<File ID>/ 403 (Forbidden)
Error: Request failed with status code 403
at createError (createError.js?2d83:16)
at settle (settle.js?467f:18)
at XMLHttpRequest.handleLoad (xhr.js?b50d:77)

Edge is serving API from cache even after passing cache-control and pragma headers

API is being fetched from cache. This is happening only in Edge. I went through many similar questions in stackoverflow and tried everything but in vain.
I added cache related headers in Vue js
axios.defaults.headers.common['Cache-Control'] = 'private, no-cache, no-store, must-revalidate'
axios.defaults.headers.common['Expires'] = 0
axios.defaults.headers.common['Pragma'] = 'no-cache'
axios.defaults.headers.common['If-Modified-Since'] = 'Mon, 26 Jul 1997 05:00:00 GMT'
I also added cache headers from server side.
[ResponseCache(NoStore = true, Location = ResponseCacheLocation.None)]
[ServiceFilter(typeof(AuthenticateFilter))]
[Produces("application/json")]
[Route("{tenant}")]
public class DashboardController : Controller
{
}
My Request headers looks like in chrome
Accept: application/json, text/plain, */*
Authorization: Token ggggggggggggggggggggg
Cache-Control: private, no-cache, no-store, must-revalidate
Expires: 0
If-Modified-Since: Mon, 26 Jul 1997 05:00:00 GMT
Origin: http://somedummy.com
Pragma: no-cache
Referer: http://somedummy.com/dashboard/sample
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36
withCredentials: true
And response headers :
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://somedummy.com
Cache-Control: no-store,no-cache
Content-Type: application/json; charset=utf-8
Date: Mon, 11 Mar 2019 08:35:36 GMT
Pragma: no-cache
Strict-Transport-Security: max-age=31536000; includeSubDomains;
Transfer-Encoding: chunked
Vary: Origin
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-Powered-By: ASP.NET
X-StackifyID: V1|b6841c38-3ec0-4a46-ac24-699ac8a5af0d|
X-XSS-Protection: 1; mode=block
APIs are being fetched from server in IE, chrome and safari but only in Edge it is being served from cache even though "Always refresh from server" option in developer option is selected.
I also have added meta in index.html
<meta http-equiv="expires" content="-1">
<meta http-equiv="cache-control" content="max-age=0">
<meta http-equiv="cache-control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="pragma" content="no-cache">
There are no errors in console. No preflight (OPTIONS) call going from Edge. Strange thing is when fiddler is open then APIs are being served from server in Edge.
Thanks in advance.
Your modification is a Server Response, this won't work, instead you should use headers: { Pragma: 'no-cache' }
Example:
const api = axios.create({
headers: { Pragma: 'no-cache' },
});
Or add it to the configuration
const config = {
headers: { Pragma: 'no-cache'},
params: { id: this.state.taskID }
}
axios.get("some URL", config).then(...)

UseExceptionHandler() middleware in .NET Core MVC prevents response headers setting

Startup.cs:
// ...
app.Use(async (context, next) =>
{
context.Response.Headers.Add("X-Frame-Options", "DENY");
context.Response.Headers.Add("X-Content-Type-Options", "nosniff");
context.Response.Headers.Add("Server", "ololo");
await next();
});
if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); }
else { app.UseExceptionHandler("/Home/Error"); }
app.UseStaticFiles();
app.UseAuthentication();
// ...
When everything is fine, I get the following headers, as expected:
HTTP/1.1 200 OK
Connection: close
Date: Mon, 30 Jul 2018 18:39:33 GMT
Content-Type: text/html; charset=utf-8
Server: ololo
Transfer-Encoding: chunked
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
So Server, X-Frame-Options and X-Content-Type-Options headers are overridden.
But if I have an unhandled exception in my code, then I get these headers:
HTTP/1.1 500 Internal Server Error
Connection: close
Date: Mon, 30 Jul 2018 18:35:49 GMT
Content-Type: text/html; charset=utf-8
Server: Kestrel
Cache-Control: no-cache
Pragma: no-cache
Transfer-Encoding: chunked
Expires: -1
So headers are not overridden.
Why is that? Is it by design? Does Exceptions middleware work differently so it doesn't go through the whole pipeline?
dotnet --info
.NET Command Line Tools (2.1.4)
Product Information:
Version: 2.1.4
Commit SHA-1 hash: 5e8add2190
Microsoft .NET Core Shared Framework Host
Version : 2.0.5
Build : 17373eb129b3b05aa18ece963f8795d65ef8ea54
A more reliable way to set the headers in any case would be to use the OnStarting callback. See docs.
Adds a delegate to be invoked just before response headers will be sent to the client.
public async Task Invoke(HttpContext context)
{
context.Response.OnStarting(() =>
{
context.Response.Headers.Add("X-Frame-Options", "DENY");
context.Response.Headers.Add("X-Content-Type-Options", "nosniff");
context.Response.Headers.Add("Server", "ololo");
return Task.CompletedTask;
});
await _next(context);
}
OnStarting will be invoked, just before the response headers are written to the wire. This allows you to set the headers after the exception middleware did handle it

How to correctly handle multiple Set-Cookie headers in Hyper?

I'm using Hyper to send HTTP requests, but when multiple cookies are included in the response, Hyper will combine them to one which then fails the parsing procedure.
For example, here's a simple PHP script
<?php
setcookie("hello", "world");
setcookie("foo", "bar");
Response using curl:
$ curl -sLD - http://local.example.com/test.php
HTTP/1.1 200 OK
Date: Sat, 24 Dec 2016 09:24:04 GMT
Server: Apache/2.4.25 (Unix) PHP/7.0.14
X-Powered-By: PHP/7.0.14
Set-Cookie: hello=world
Set-Cookie: foo=bar
Content-Length: 0
Content-Type: text/html; charset=UTF-8
However for the following Rust code:
let client = Client::new();
let response = client.get("http://local.example.com/test.php")
.send()
.unwrap();
println!("{:?}", response);
for header in response.headers.iter() {
println!("{}: {}", header.name(), header.value_string());
}
...the output will be:
Response { status: Ok, headers: Headers { Date: Sat, 24 Dec 2016 09:31:54 GMT, Server: Apache/2.4.25 (Unix) PHP/7.0.14, X-Powered-By: PHP/7.0.14, Set-Cookie: hello=worldfoo=bar, Content-Length: 0, Content-Type: text/html; charset=UTF-8, }, version: Http11, url: "http://local.example.com/test.php", status_raw: RawStatus(200, "OK"), message: Http11Message { is_proxied: false, method: None, stream: Wrapper { obj: Some(Reading(SizedReader(remaining=0))) } } }
Date: Sat, 24 Dec 2016 09:31:54 GMT
Server: Apache/2.4.25 (Unix) PHP/7.0.14
X-Powered-By: PHP/7.0.14
Set-Cookie: hello=worldfoo=bar
Content-Length: 0
Content-Type: text/html; charset=UTF-8
This seems to be really weird to me. I used Wireshark to capture the response and there're two Set-Cookie headers in it. I also checked the Hyper documentation but got no clue...
I noticed Hyper internally uses a VecMap<HeaderName, Item> to store the headers. So they concatenate the them to one? Then how should I divide them into individual cookies afterwards?
I think that Hyper prefers to keep the cookies together in order to make it easier do some extra stuff with them, like checking a cryptographic signature with CookieJar (cf. this implementation outline).
Another reason might be to keep the API simple. Headers in Hyper are indexed by type and you can only get a single instance of that type with Headers::get.
In Hyper, you'd usually access a header by using a corresponding type. In this case the type is SetCookie. For example:
if let Some (&SetCookie (ref cookies)) = response.headers.get() {
for cookie in cookies.iter() {
println! ("Got a cookie. Name: {}. Value: {}.", cookie.name, cookie.value);
}
}
Accessing the raw header value of Set-Cookie makes less sense, because then you'll have to reimplement a proper parsing of quotes and cookie attributes (cf. RFC 6265, 4.1).
P.S. Note that in Hyper 10 the cookie is no longer parsed, because the crate that was used for the parsing triggers the openssl dependency hell.

jquery.ajax() POST receives empty response with IE10 on Nginx/PHP-FPM but works on Apache

I use a very simple jquery.ajax() call to fetch some HTML snippet from a server:
// Init add lines button
$('body').on('click', '.add-lines', function(e) {
$.ajax({
type : 'POST',
url : $(this).attr('href')+'?ajax=1&addlines=1',
data : $('#quickorder').serialize(),
success : function(data,x,y) {
$('#directorderform').replaceWith(data);
},
dataType : 'html'
});
e.preventDefault();
});
On the PHP side i basically echo out a HTML string. The jQuery version is 1.8.3.
The problem is in IE10: While it works fine there on Server A which runs on Apache it fails on Server B which runs on Nginx + PHP-FPM: If i debug the success handler on Server B I get a undefined for data. In the Network tab of the IE developer tools I can see the full response and all headers. It may affect other IE versions, but i could only test IE10 so far.
Here are the two response headers:
Server A, Apache (works):
HTTP/1.1 200 OK
Date: Thu, 25 Apr 2013 13:28:08 GMT
Server: Apache
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Vary: Accept-Encoding,User-Agent
Content-Encoding: gzip
Content-Length: 1268
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8
Server B, Nginx + PHP-FPM (fails):
HTTP/1.1 200 OK
Server: nginx/1.1.19
Date: Thu, 25 Apr 2013 13:41:43 GMT
Content-Type: text/html; charset=utf8
Transfer-Encoding: chunked
Connection: keep-alive
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Content-Encoding: gzip
The body part looks the same in both cases.
Any idea what could cause this issue?
Please also check the Content-Type Header, since Apache and Nginx are sending different values:
Content-Type: text/html; charset=UTF-8
vs.
Content-Type: text/html; charset=utf8
Update your Nginx config, add this line:
charset UTF-8;