When opening a link to a PNG image on Imgur, for example https://i.stack.imgur.com/jZPcm.png, in Google Chrome, then the image is displayed in the browser.
But when uploading a PNG to a bucket on Amazon S3, when the link is opened, the image not viewed rather it is asked to download. I've tried setting the 'Content-Type' on the S3 image, but wihout luck.
Headers on Imgur:
{'Date': 'Tue, 11 Aug 2020 10:31:05 GMT', 'Content-Type': 'image/png', 'Content-Length': '18782', 'Connection': 'keep-alive', 'Set-Cookie': '__cfduid=d7f5ddd0f60e3db9cc4edffeedd30f3e71597141865; expires=Thu, 10-Sep-20 10:31:05 GMT; path=/; domain=.imgur.com; HttpOnly; SameSite=Lax', 'Cache-Control': 'public, max-age=315360000', 'ETag': '"187ec0eb8d9d14b438e87ea698efac33"', 'Expires': 'Fri, 09 Aug 2030 10:31:05 GMT', 'Last-Modified': 'Thu, 07 Dec 2017 11:01:07 GMT', 'x-amz-version-id': 'ON9e1QkM1BPSMbeDWGHFgxksnolmRP7Q', 'CF-Cache-Status': 'HIT', 'Age': '50', 'Accept-Ranges': 'bytes', 'cf-request-id': '047eabece000009e37d08e1200000001', 'Expect-CT': 'max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"', 'Vary': 'Accept-Encoding', 'Server': 'cloudflare', 'CF-RAY': '5c1148f49ac79e37-ATH'}
Headers on S3
{'x-amz-id-2': 'apFCJaAW2DSB75jrhb88BhuSHGNV6oWW9/RhPhMxSsvdELqEuzeBED6wDrcpZ8o9rzS+v9kVrp0=', 'x-amz-request-id': 'CC00D77EB673C6B7', 'Date': 'Tue, 11 Aug 2020 10:30:50 GMT', 'Last-Modified': 'Tue, 11 Aug 2020 10:18:59 GMT', 'ETag': '"3e8fd2271360bb9b73f2c5dad4cab18a"', 'Accept-Ranges': 'bytes', 'Content-Type': 'image/png', 'Content-Length': '132662', 'Server': 'AmazonS3'}
Both have the same content type.
In order to display the image inside the Web page, you can add a metadata key Content-Disposition with the value of inline. [ref]
Related
I'm tearing my hair out trying to get a simple PATCH API call to change a value in my table. I'm using airtable.
I have a table, named AllTitles, which contains information regarding movies. I have a field in this table called 'liked' and the aim is to assign a value 1 to this cell when the user clicks a button. So I figured and nice simple PATCH would work. I set the default value to 0. The idea being that the title is marked as being liked, so I can filter liked titles and return these to the app.
The KEY value for my table is called myid. I have added a column which calls the function RECORD ID() and this does indeed display the unique record id. I'm using bravo studio, which turns figma design into an app, and using their backend I generate the URL. The URL contains a variable at the end, you guessed it, the record id. When I copy and paste this URL into the browser bar it loads the correct record. However, I am getting a 404 error when I debug.
Request Header:
application/json, text/plain, */*
Content-Type:
application/json
user-agent:
Bravo Data/1.0
Authorization:
Bearer ***
Host:
airtable.com
Content-Length:
24
(API key is correct and GET requests are working fine)
Body of request
"fields": {
"liked": "1"
}
}
Error:
Response Header:
Wed, 25 Jan 2023 17:42:54 GMT
content-type:
text/html; charset=utf-8
content-length:
246156
connection:
close
set-cookie:
AWSALB=F+leSSpTg+mrYU4Zht2ykcCKh8q7PTwcfEPi+wMpFNAocaVY2+FM1HO+w4/Jlk27DietrhMCMPM+SgKbtOlamaShWtfbhOlE7uDJGeD77VI2eClhFgNuws5gS+Hw; Expires=Wed, 01 Feb 2023 17:42:54 GMT; Path=/AWSALBCORS=F+leSSpTg+mrYU4Zht2ykcCKh8q7PTwcfEPi+wMpFNAocaVY2+FM1HO+w4/Jlk27DietrhMCMPM+SgKbtOlamaShWtfbhOlE7uDJGeD77VI2eClhFgNuws5gS+Hw; Expires=Wed, 01 Feb 2023 17:42:54 GMT; Path=/; SameSite=None; Securebrw=brwCHhGJtay2UWLI4; path=/; expires=Thu, 25 Jan 2024 17:42:54 GMT; domain=.airtable.com; samesite=none; securelogin-status-p=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT; domain=.airtable.com; secure__Host-airtable-session=eyJzZXNzaW9uSWQiOiJzZXNDNTRZWDdkYzBqTjNRcCJ9; path=/; expires=Fri, 26 Jan 2024 17:42:54 GMT; samesite=none; secure; httponly__Host-airtable-session.sig=aXS4bLusbVBSn5HWa3ScJv3_LC0hyYkl-cD_B5101m0; path=/; expires=Fri, 26 Jan 2024 17:42:54 GMT; samesite=none; secure; httponly
server:
Tengine
strict-transport-security:
max-age=31536000; includeSubDomains; preload
x-frame-options:
SAMEORIGIN
x-xss-protection:
1; mode=block
x-content-type-options:
nosniff
content-security-policy-report-only:
style-src 'unsafe-inline' https:; block-all-mixed-content; object-src 'none'; base-uri 'none'; report-uri https://airtable.com/.csp/report; script-src 'nonce-9IaceKDUeI02' 'unsafe-inline' 'strict-dynamic' 'report-sample' https:
referrer-policy:
same-origin
etag:
W/"3c18c-skDWN0GQdQY5H9HT6YcIG4hRKIQ"
vary:
Accept-Encoding
Response Body:
"<!DOCTYPE html>\n<html style=\"overflow:auto\" lang=\"en\"><head><meta name=\"referrer\" content=\"no-referrer\"/><meta name=\"robots\" content=\"noindex\"/><meta charSet=\"utf-8\"/><meta name=\"theme-color\" content=\"#ffffff\"/><meta name=\"description\" content=\"Airtable is a low-code platform for building collaborative apps. Customize your workflow, collaborate, and achieve ambitious outcomes. Get started for free.\"/><meta name=\"apple-itunes-app\" content=\"app-id=914172636\"/><meta name=\"twitter:card\" content=\"summary_large_image\"/><meta name=\"twitter:site\" content=\"#airtable\"/><meta property=\"fb:app_id\" content=\"1457397314575627\"/><meta property=\"og:site_name\" content=\"Airtable\"/><meta property=\"og:title\" content=\"Airtable | Everyone's app platform\"/><meta property=\"og:type\" content=\"website\"/><meta property=\"og:description\" content=\"Airtable is a low-code platform for building collaborative apps. Customize your workflow, collaborate, and achieve ambitious outcomes. Get started for free.\"/><meta property=\"og:image\" content=\"https://static.airtable.com/images/oembed/airtable.png\"/><meta http-equiv=\"x-ua-compatible\" content=\"ie=edge\"/><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"/><title>Page not found - Airtable</title><script nonce=\"9IaceKDUeI02\" src=\"https://static.airtable.com/js/lib/onetrust/202211.1.0/scripttemplates/otSDKStub.js\" data-domain-script=\"2eda840d-10c3-46d7-9084-4cade1b1a306\"></script><script nonce=\"9IaceKDUeI02\" src=\"https://static.airtable.com/js/lib/onetrust/202211.1.0/consent/2eda840d-10c3-46d7-9084-4cade1b1a306/OtAutoBlock.js\"></script><link nonce=\"9IaceKDUeI02\" rel=\"stylesheet\" type=\"text/css\" href=\"/css/compiled/baymax/helpers.css?v=27c119df61346f4f-7\"/><link rel=\"apple-touch-icon\" sizes=\"180x180\" href=\"/images/favicon/baymax/apple-touch-icon.png\"/><link rel=\"icon\" type=\"image/png\" href=\"/images/favicon/baymax/favicon-32x32.png\" sizes=\"32x32\"/><link rel=\"icon\" type=\"image/png\" href=\"/images/favicon/baymax/favicon-16x16.png\" sizes=\"16x16\"/><link rel=\"manifest\" href=\"/images/favico..."
There are no query parameters set. I am at a loss as to what can be the problem when the generated URL works perfectly. It's not the most demanding JSON PATCH request in the world....
I'm working on Google chrome push notification with data payload and I am using the npm web-push. In my push api I called the function sendNotification() and passed the endpoint and the required parameters - public key, authkey and the data payload (string).
But when I tried to push the notification msg to GCM, I always get the below error from GCM.
Error occurred! { [WebPushError: Received unexpected response code]
name: 'WebPushError',
message: 'Received unexpected response code',
statusCode: 400,
headers:
{ 'content-type': 'text/html; charset=UTF-8',
date: 'Fri, 05 Aug 2016 17:26:59 GMT',
expires: 'Fri, 05 Aug 2016 17:26:59 GMT',
'cache-control': 'private, max-age=0',
'x-content-type-options': 'nosniff',
'x-frame-options': 'SAMEORIGIN',
'x-xss-protection': '1; mode=block',
server: 'GSE',
'alternate-protocol': '443:quic',
'alt-svc': 'quic=":443"; ma=2592000; v="36,35,34,33,32,31,30"',
'accept-ranges': 'none',
vary: 'Accept-Encoding',
connection: 'close' },
body: '<HTML>\n<HEAD>\n<TITLE>UnauthorizedRegistration</TITLE>\n</HEAD>\n<BODY BGCOLOR="#FFFFFF" TEXT="#000000">\n<H1>UnauthorizedRegistration</H1>\n<H2>Error 400</H2>\n</BODY>\n</HTML>\n' }
Does anyone have any idea or suggestion?
I have an image saved on my AWS S3 bucket. This is my CORS configuration:
<CORSConfiguration>
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>Authorization</AllowedHeader>
</CORSRule>
</CORSConfiguration>
Also, the bucket has this policy:
{
"Version": "2012-10-17",
"Id": "Policy1468082822770",
"Statement": [
{
"Sid": "Stmt1468082812651",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::criptolibertad/*"
}
]
}
This is the image: https://criptolibertad.s3.amazonaws.com/Django/0_startproject.jpeg , as you can see, it is public. I use a library called Croppie that tries to load the image into a canvas. But the canvas doesn't show the image I don't know why. The js looks like this:
croppie_div.croppie('bind', {
url: "{{ carta_magicpy.imagen_base.url }}",
points: [10,10,300,600]
});
That url attribute is just a variable rendered by Django. It looks like this when it is rendered:
<img style="opacity: 0;" src="https://criptolibertad.s3.amazonaws.com/Django/0_startproject.jpeg" crossorigin="anonymous" class="cr-image">
Notice the crossorigin attribute. I went into Croppie's source and removed that attribute. But then I get the error:
Image from origin ... has been blocked from loading by Cross-Origin Resource Sharing policy:
No 'Access-Control-Allow-Origin' header is present on the requested
resource
How can I solve this?
Seems the CORS headers are still not set correctly. This related Croppie issue #119 mentions you can check that by looking at the response headers.
It's pretty easy to inspect the headers with curl, for the image stored in your bucket:
curl -I -H "Origin: https://stackoverflow.com/questions/38365182" -H "Access-Control-Request-Method: GET" https://criptolibertad.s3.amazonaws.com/Django/0_startproject.jpeg
HTTP/1.1 200 OK
x-amz-id-2: 9AaMwS9s2Im+OV6YlzVKrDW8RnbQqFt4Ygc+pRa3XM4iDmnJqlO8DQ7EjvpT4W4GnhGc0IvoQeI=
x-amz-request-id: CD4E7C50B5186192
Date: Fri, 15 Jul 2016 07:54:52 GMT
Last-Modified: Sat, 09 Jul 2016 05:13:33 GMT
ETag: "5733f7cd0187eb3a840bbe83e2c66a9b"
Accept-Ranges: bytes
Content-Type: image/jpeg
Content-Length: 33402
Server: AmazonS3
As opposed to the properly set up CORS headers on e.g imgur:
curl -I -H "Origin: https://stackoverflow.com/questions/38365182" -H "Access-Control-Request-Method: GET" http://i.imgur.com/HMf7XWD.jpg
HTTP/1.1 200 OK
Last-Modified: Wed, 06 Jul 2016 15:07:13 GMT
ETag: "7b01be4b9235542038f6d9793cc2c620"
Content-Type: image/jpeg
Fastly-Debug-Digest: f94b623450bb8143aff369600bf855d6332bb44c12070f02b0fc95648eac6ef3
cache-control: public, max-age=31536000
Content-Length: 2457350
Accept-Ranges: bytes
Date: Fri, 15 Jul 2016 07:55:15 GMT
Age: 277937
Connection: keep-alive
X-Served-By: cache-iad2131-IAD, cache-fra1232-FRA
X-Cache: HIT, HIT
X-Cache-Hits: 1, 1
X-Timer: S1468569315.725739,VS0,VE2
Access-Control-Allow-Methods: GET, OPTIONS
Access-Control-Allow-Origin: *
Server: cat factory 1.0
As you can see the main difference is that imgur returns the headers Access-Control-Allow-Methods and Access-Control-Allow-Origin, while your S3 bucket does not.
I have followed the official Amazon documentation on the subject and applied the modified CORS configuration to my own bucket, the difference from your configuration is the AllowedHeader element, which defines the headers to allowed in response. I set my bucket to:
<AllowedHeader>*</AllowedHeader>
Here are the resulting headers on the image stored in my bucket:
curl -I -H "Origin: https://stackoverflow.com/questions/38365182" -H "Access-Control-Request-Method: GET" https://so38134984.s3.amazonaws.com/rainbow_dash.png
HTTP/1.1 200 OK
x-amz-id-2: ANxPKoL3JDsLDGerTf8gdcyRU7U4Ozg4eMYJ9ADlX/2qcBmx0dsmAbZxv2h/tFfQIXbkAs+x5iA=
x-amz-request-id: 737E30AE2F8634FC
Date: Fri, 15 Jul 2016 07:53:55 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET
Access-Control-Max-Age: 3000
Vary: Origin, Access-Control-Request-Headers, Access-Control-Request-Method
Last-Modified: Mon, 04 Jul 2016 20:09:19 GMT
ETag: "3ad1bb64b913c2eadab216b96034b990"
Accept-Ranges: bytes
Content-Type: image/png
Content-Length: 148647
Server: AmazonS3
I assume my image will now work properly in your Croppie script.
I am testing a script for logout and access a URL not accessible when you are not logged in, but in my URL LOGOUT, i get the response code 405 and this is problematic.
Code:
$I = new AcceptanceTester($scenario);
$I->amOnPage('/financeiro_legado/finlegado-titulo/index');
$I->wantTo('Logout');
$I->amOnPage('/');
$I->fillField('LoginForm[username]', 'marcelo');
$I->fillField('LoginForm[password]', 'marceloid5123');
$I->click('#login-form .btn');
$I->see('Olá, marcelo');
$I->seeInCurrentUrl('/');
$I->click('Logout', '.nav');
$I->amOnPage('/financeiro_legado/finlegado-titulo/index');
Returns:
Logout (LogoutCept)
Scenario:
* I am on page "/financeiro_legado/finlegado-titulo/index"
[Response] 200
[Page] http://10.0.0.10/CliPainel/backend/web/index.php/user-management/auth/login
[Cookies] {"PHPSESSID":"puu268lb5rjl00ml0hk27rm9b0"}
[Headers] {"Date":["Fri, 11 Dec 2015 17:34:13 GMT"],"Server":["Apache/2.4.17 (Ubuntu)"],"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"],"Set-Cookie":["_csrf=07c2d101d6c9e8530f7da67a78d451400eea99b70dc8a722a512661501bc4619a%3A2%3A%7Bi%3A0%3Bs%3A5%3A%22_csrf%22%3Bi%3A1%3Bs%3A32%3A%2248-nrt97Wc-EEUA0jUh6-USBTS-44ccy%22%3B%7D; path=/; httponly"],"Vary":["Accept-Encoding"],"Content-Length":["3918"],"Content-Type":["text/html; charset=UTF-8"]}
* I am on page "/"
[Response] 200
[Page] http://10.0.0.10/CliPainel/backend/web/index.php/user-management/auth/login
[Cookies] {"PHPSESSID":"puu268lb5rjl00ml0hk27rm9b0","_csrf":"07c2d101d6c9e8530f7da67a78d451400eea99b70dc8a722a512661501bc4619a:2:{i:0;s:5:"_csrf";i:1;s:32:"48-nrt97Wc-EEUA0jUh6-USBTS-44ccy";}"}
[Headers] {"Date":["Fri, 11 Dec 2015 17:34:14 GMT"],"Server":["Apache/2.4.17 (Ubuntu)"],"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"],"Content-Length":["3918"],"Content-Type":["text/html; charset=UTF-8"]}
* I fill field "LoginForm[username]","marcelo"
* I fill field "LoginForm[password]","marceloid5123"
* I click "#login-form .btn"
[Uri] http://10.0.0.10/CliPainel/backend/web/index.php/user-management/auth/login
[Method] POST
[Parameters] {"_csrf":"bWN1ZS1zWTBZW1gLXwdgBzoAWCBoJhgABzYdUwAmCnI5MFhRGRA6SQ==","LoginForm":{"username":"marcelo","password":"marceloid5123"}}
[Response] 200
[Page] http://10.0.0.10/CliPainel/backend/web/
[Cookies] {"PHPSESSID":"6hehrk4ddoroplv5so3l6klkb1","_csrf":"07c2d101d6c9e8530f7da67a78d451400eea99b70dc8a722a512661501bc4619a:2:{i:0;s:5:"_csrf";i:1;s:32:"48-nrt97Wc-EEUA0jUh6-USBTS-44ccy";}"}
[Headers] {"Date":["Fri, 11 Dec 2015 17:34:16 GMT"],"Server":["Apache/2.4.17 (Ubuntu)"],"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"],"Transfer-Encoding":["chunked"],"Content-Type":["text/html; charset=UTF-8"]}
* I see "Olá, marcelo"
* I see in current url "/"
* I click "Logout",".nav"
[Response] 405
[Page] http://10.0.0.10/CliPainel/backend/web/index.php/site/logout
[Cookies] {"PHPSESSID":"6hehrk4ddoroplv5so3l6klkb1","_csrf":"07c2d101d6c9e8530f7da67a78d451400eea99b70dc8a722a512661501bc4619a:2:{i:0;s:5:"_csrf";i:1;s:32:"48-nrt97Wc-EEUA0jUh6-USBTS-44ccy";}"}
[Headers] {"Date":["Fri, 11 Dec 2015 17:34:18 GMT"],"Server":["Apache/2.4.17 (Ubuntu)"],"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"],"Allow":["POST"],"Transfer-Encoding":["chunked"],"Content-Type":["text/html; charset=UTF-8"]}
* I am on page "/financeiro_legado/finlegado-titulo/index"
[Response] 200
[Page] http://10.0.0.10/CliPainel/backend/web/financeiro_legado/finlegado-titulo/index
[Cookies] {"PHPSESSID":"6hehrk4ddoroplv5so3l6klkb1","_csrf":"07c2d101d6c9e8530f7da67a78d451400eea99b70dc8a722a512661501bc4619a:2:{i:0;s:5:"_csrf";i:1;s:32:"48-nrt97Wc-EEUA0jUh6-USBTS-44ccy";}"}
[Headers] {"Date":["Fri, 11 Dec 2015 17:34:19 GMT"],"Server":["Apache/2.4.17 (Ubuntu)"],"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"],"Transfer-Encoding":["chunked"],"Content-Type":["text/html; charset=UTF-8"]}
PASSED
Probably you handle that click with Javascript in the web browser.
Yii2 module of Codeception does not execute Javascript.
Your options are:
a) make your site work with Javascript disabled.
You could achieve that by changing
Logout
To
<form method="POST" action="site/logout">
<input type="submit" value="Logout" />
</form>
b) Use sendAjaxPostRequest method to make POST request
$I->sendAjaxPostRequest('site/logout', []);
The last few hours, I have tried to figure out, why the following image is not cached in the browser, after it is requested the first time:
http://runrpg.net/assets/images/screenshots/placeit_outdoor_wide.jpg
I understand that the correct headers have to be set, and currently the response header looks like this:
HTTP/1.1 200 OK
Date: Sat, 04 Jan 2014 16:35:53 GMT
Server: Apache/2.4.4 (Unix) OpenSSL/1.0.1e PHP/5.5.3 mod_perl/2.0.8-dev
Perl/v5.16.3
Last-Modified: Sat, 30 Nov 2013 01:37:52 GMT
ETag: "1dac5-4ec5afebf3c00-gzip"
Accept-Ranges: bytes
Cache-Control: max-age=2592000
Expires: Mon, 03 Feb 2014 16:35:53 GMT
Vary: Accept-Encoding
Content-Encoding: gzip
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: image/jpeg
As you can see, the "Expires" header is set to "Mon, 03 Feb 2014 16:35:53 GMT" and I also included a "Cache-Control: max-age=2592000".
Can you help me and tell me what I am missing?
Your help would be very much appreciated.
Thanks!
This is most likely due to your server not validating ETags correctly. While cache validation through the Last-Modified header works perfectly:
$ HEAD -H "If-Modified-Since: Sat, 30 Nov 2013 01:37:52 GMT" http://runrpg.net/assets/images/screenshots/placeit_outdoor_wide.jpg
304 Not Modified
Cache-Control: max-age=290304000, public
Connection: close
Date: Sat, 04 Jan 2014 19:01:30 GMT
ETag: "1dac5-4ec5afebf3c00"
Server: Apache/2.4.4 (Unix) OpenSSL/1.0.1e PHP/5.5.3 mod_perl/2.0.8-dev Perl/v5.16.3
Expires: Thu, 09 Jan 2014 19:01:30 GMT
Client-Date: Sat, 04 Jan 2014 19:01:30 GMT
Client-Peer: 80.70.3.110:80
Client-Response-Num: 1
The same cannot be said with ETags:
$ HEAD -H 'If-None-Match: "1dac5-4ec5afebf3c00-gzip"' http://runrpg.net/assets/images/screenshots/placeit_outdoor_wide.jpg
200 OK
Cache-Control: max-age=290304000, public
Connection: close
Date: Sat, 04 Jan 2014 19:02:24 GMT
Accept-Ranges: bytes
ETag: "1dac5-4ec5afebf3c00"
Server: Apache/2.4.4 (Unix) OpenSSL/1.0.1e PHP/5.5.3 mod_perl/2.0.8-dev Perl/v5.16.3
Vary: Accept-Encoding
Content-Length: 121541
Content-Type: image/jpeg
Expires: Thu, 09 Jan 2014 19:02:24 GMT
Last-Modified: Sat, 30 Nov 2013 01:37:52 GMT
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: origin, x-requested-with, content-type, X-Titanium-Id
Access-Control-Allow-Methods: PUT, GET, POST, DELETE, OPTIONS
Access-Control-Allow-Origin: http://127.0.0.1:8020
Client-Date: Sat, 04 Jan 2014 19:02:24 GMT
Client-Peer: 80.70.3.110:80
Client-Response-Num: 1
Bottom line: The problem is your server, not any clients. This seems to be a known issue with Apache 2.4.x. A quick solution to this is by switching ETags off:
FileETag None