how to automatically set header to all files inside /storage/ folder? - php

My frontend is trying to fetch() an image from my API, which usually handles my CORS. Because it directly requests the image, circumventing the API, I receive this issue: (which makes complete sense why)
Access to XMLHttpRequest at 'https://my-api.test/storage/media/1/15/poster.jpg' from origin 'http://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
I need to adjust my Nginx settings so that any file requested living under the /storage/ path will have this header added.
I must be misunderstanding parts of how I should configure Nginx in this case, because I was believing that this location-block should have worked:
location /storage/ {
add_header 'Access-Control-Allow-Origin' '*';
}
Oddly, it returns a "404 status":
curl -I https://my-api.test/storage/test-media/butterfly.jpg
HTTP/2 404
server: nginx/1.19.4
date: Tue, 17 Nov 2020 06:57:23 GMT
content-type: image/jpeg
content-length: 116501
etag: "5f6045f4-1c715"
On the other hand, if I disable the location-block condition:
#location /storage/ {
add_header 'Access-Control-Allow-Origin' '*';
#}
The header then is properly added:
curl -I https://my-api.test/storage/test-media/butterfly.jpg
HTTP/2 200
server: nginx/1.19.4
date: Tue, 17 Nov 2020 07:00:53 GMT
content-type: image/jpeg
content-length: 116501
last-modified: Tue, 15 Sep 2020 04:41:24 GMT
etag: "5f6045f4-1c715"
access-control-allow-origin: *
accept-ranges: bytes
Any help would be truly appreciated!
edit 1
I am not sure whether it makes a difference, but the "storage" folder is a symlink.
edit 2
The nginx error:
2020/11/17 12:45:50 [error] 64990#0: *1 open() "/storage/media/1/1/turtle.jpg" failed (2: No such file or directory), client: 127.0.0.1, server: , request: "HEAD /storage/media/1/1/turtle.jpg HTTP/1.1", host: "my-api.test"
When I try to visit the URL in the browser my-api.test/storage/media/1/1/turtle.jpg it returns the image and not a 404.

The solution to this problem was rather simple:
location /storage/ {
root '/Users/chrisbreuer/code/my-api/public';
add_header 'Access-Control-Allow-Origin' "*" always;
}
As you can see, the location-block is now adding a root which is where the "storage" folder lives in.
In my case, I was using Laravel Valet and when you have a secure site, you would need to adjust the nginx config file which is located in this path: ~/.config/valet/Nginx/meema-api.test.
Now, simply run valet restart and all files requested from within the storage-folder will have the header included.

Related

Headers sent already before any output with PHP, Nginx on Azure

I have two hosting environments, one is running PHP 7.4 with Apache, and the other one is running PHP 8.1 with Nginx both on Azure.
I run this PHP script on both:
<?php ini_set("display_errors", 1); header('Status: 301 Moved Permanently', true, 301); ?>
When I run this code on host 1, I get what I expect; the headers are output as 301:
D:\home\site\wwwroot>curl -is test.php
HTTP/1.1 301 Moved Permanently
Content-Length: 0
Content-Type: text/html; charset=utf-8
Date: Fri, 25 Nov 2022 08:46:09 GMT
Server: Microsoft-IIS/10.0
X-Powered-By: PHP/7.4.30
X-Powered-By: ASP.NET
Running the same script om the Nginx environement under PHP 8.1 I get:
root:/home# curl -is localhost:8080
HTTP/1.1 200 OK
Server: nginx/1.22.1
Date: Fri, 25 Nov 2022 08:45:33 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
X-Powered-By: PHP/8.1.9
<br />
<b>Warning</b>: Cannot modify header information - headers already sent by (output started at /home/site/wwwroot/index.php:1) in <b>/home/site/wwwroot/index.php</b> on line <b>1</b><br />
As you can see the header 301 could not be sent because the 200 header was already sent.
There is absolutely nothing before the first <?php-tag.
I have tried lots of things with the Nginx config, but no result. Is this something that is inside PHP.INI?
What is causing the header 200 to be sent before any line of my PHP script?
Solution: output_buffering is apparently disabled by default, you can turn it on in the INI of PHP, like so:
Create a folder inside /home/site called ini
Add a file there with the extention .ini, like site.ini
Add this line and save:
output_buffering = on
Go to your azure portal to the webapp and inside Configuration add an application setting with name = PHP_INI_SCAN_DIR and value = /usr/local/etc/php/conf:/home/site/ini
Then save the application setting witch will restart your app.

How to solve Access-control-Allow_origin in codeigniter

I have just converted an HTML template to php. I have put the folders like css,js,and images at the root directory of codeigniter project. Using base_url function I have successfully fetched images and styles yet some of the icons are still missing and I am getting this error in console
Access to font at 'http://[::1]/diz/fonts/themify.woff?-fvbane' from origin 'http://localhost' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
I have also put this line in my controller that loads the view of index page
header('Access-Control-Allow-Origin: *');
I expected it to solve the problem but it is not doing anything. I have also tried answers given by others here, but it did not help.
Thanks in advance
The response header in network is :
HTTP/1.1 200 OK
Date: Wed, 06 Nov 2019 10:32:51 GMT
Server: Apache/2.4.33 (Win32) OpenSSL/1.1.0h PHP/7.2.6
Last-Modified: Tue, 12 Mar 2019 09:38:36 GMT
ETag: "db2c-583e27406bf00"
Accept-Ranges: bytes
Content-Length: 56108
Content-Type: font/woff
Try to use
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Methods: GET, OPTIONS");
If it not works u can try to configure your local server
Apache:
<FilesMatch ".(ttf|otf|eot|woff|woff2)$">
<IfModule mod_headers.c>
Allow from all
Header set Access-Control-Allow-Origin "*"
</IfModule>
</FilesMatch>
and Nginx:
if ($filename ~* ^.*?\.(eot)|(ttf)|(woff)$){
add_header Access-Control-Allow-Origin *;
}

How to set proxy for AJAX calls in a simple react app?

I created simple react app as described in https://reactjs.org/docs/add-react-to-a-new-app.html and now want to make AJAX calls to the webserver (with PHP). To make it working with development server at localhost:3000 I am trying to set up proxy in package.json
"proxy": {
"/abc": {
"target": "http://web.local/app/path/public/abc",
"secure": false,
"changeOrigin": true,
"logLevel": "debug"
}
}
Unfortunately app answers with default index.html content. How to make proxy working when requesting /abc path?
Is there any way to test and debug proxy? When I try to open http://localhost:3000/abc I can see
[HPM] POST /abc/abc -> http://web.local/app/path/public/abc
in console. But there is no messages when I'm loading app and request is sent from the app. (I tried fetch and axios calls.)
When I build app and run it on web server, all works fine.
EDIT:
Response Headers for the axios ajax call:
HTTP/1.1 404 Not Found
X-Powered-By: Express
Content-Security-Policy: default-src 'self'
X-Content-Type-Options: nosniff
Content-Type: text/html; charset=utf-8
Content-Length: 143
Vary: Accept-Encoding
Date: Wed, 03 Jan 2018 17:44:02 GMT
Connection: keep-alive
For fetch:
HTTP/1.1 301 Moved Permanently
X-Powered-By: Express
Content-Type: text/html; charset=UTF-8
Content-Length: 165
Content-Security-Policy: default-src 'self'
X-Content-Type-Options: nosniff
Location: /abc/
Vary: Accept-Encoding
Date: Wed, 03 Jan 2018 17:58:37 GMT
Connection: keep-alive
And
HTTP/1.1 200 OK
X-Powered-By: Express
Accept-Ranges: bytes
Content-Type: text/html; charset=UTF-8
ETag: W/"649-W8GnY7MkgPFg6/GXObpRHPnVDeU"
Vary: Accept-Encoding
Content-Encoding: gzip
Date: Wed, 03 Jan 2018 17:58:37 GMT
Connection: keep-alive
Transfer-Encoding: chunked
I resolved issue. My php files were located in public/ dir of the app (to have them included in build). And it is accessible from development web server as static content. Now proxy checks if file exists in public/ and delivers it if possible. And if there is no such file, then rules are applied and it tries to fetch data from specified URL.
So I moved all php related files to other location and needed data are delivered from web server through proxy as inteded just with
"proxy": "http://web.local/app/path/static"
in package.json.
Also I had to add separate command to copy content of this dir to build/ and add it to build process.

HAProxy health check not working but CURL returns 200 OK

I have a HAProxy health check configured with the following backend:
backend php_servers
http-request set-header X-Forwarded-Port %[dst_port]
option httpchk get /health
http-check expect status 200
server php1 internal_ip:80 check
HAProxy doesn't enable the server but when using CURL I receive a 200 OK response.
Command: curl -I internal_ip/health
Response:
HTTP/1.1 200 OK
Server: nginx
Date: Thu, 01 Dec 2016 20:53:48 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
Access-Control-Allow-Origin: api.flex-appeal.nl
X-Frame-Options: SAMEORIGIN
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-transform
Why doesn't HAProxy recognize the servers as "UP"? Seems I can connect just fine.
The correct HTTP verb is GET, not get:
option httpchk GET /health
You can also check/enable the stats page: on the LastChk column you will see why the check fails. In my case, I get a 501 Not Implemented response.
I can reproduce it by doing the same request as HAProxy:
$ telnet localhost 80
Trying ::1...
Connected to localhost.
Escape character is '^]'.
get /health HTTP/1.0
HTTP/1.1 501 Not Implemented
Date: Thu, 01 Dec 2016 21:53:09 GMT
Server: Apache/2.4.23 (Unix) PHP/7.0.13
[...]

Content-Length header on HHVM FastCGI is intermittent

Maybe it's the jetlag, but I'm failing to make PHP/HHVM give me the Content-Type header when I need it.
I've deployed the full stack (MySQL, HHVM, Nginx) on a Vagrant machine and I've managed to reproduce the issue on a test script:
<?php
$file='/usr/share/doc/iptables/html/NAT-HOWTO.html'; # random test file
header('Content-Length: ' . filesize($file));
echo(readfile($file));
?>
If you examine the headers with curl:
hostname:~ jsimpson$ curl -I http://vagrant/test.php
HTTP/1.1 200 OK
Server: nginx/1.4.6 (Ubuntu)
Date: Tue, 16 Sep 2014 22:09:25 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 2592
Connection: keep-alive
X-Powered-By: HHVM/3.2.0
Content-Encoding: none;
We have a content length header. However if we hit the same URL from Chrome, and get the headers from the Dev tools:
HTTP/1.1 200 OK
Server: nginx/1.4.6 (Ubuntu)
Date: Tue, 16 Sep 2014 22:14:41 GMT
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
X-Powered-By: HHVM/3.2.0
Content-Encoding: gzip
No Content-Length header. I've also packet sniffed this to verify that the header isn't sent. I can switch to PHP FPM and it sends the header.
I reproduced the issue by hitting the server with:
curl -H 'Accept-Encoding: gzip,deflate' --compressed -v http://foo/bar
HHVM enables compression by default. Disabling that gave me the header back.
Everything was awesome after adding this to /etc/hhvm/server.ini
hhvm.server.gzip_compression_level = 0
I stumbled upon this issue/feature. Not running HHVM though. Pure nginx + PHP-FPM.
The thing is, if your PHP app calculates and sets Content-Lenght header field, and your nginx is configured to gzip content, it will just ditch this information and replace it by Chunked transfer encoding and GZIP headers.
So do not set GZIP to a very small buffers, default is 20 bytes which does quite the opposite (end result is larger then before GZIP compression).
I set it like this:
gzip_min_length 1024;

Categories