Exclude api request only, from https??

Joined
Sep 12, 2016
Messages
28
Likes
4
Degree
0
Hello Builders,
Is there a way to exclude api requests only and let those come through as http, I force all my traffic thru https via my nginx site config (see code below) but I need to exclude all requests to xx.com/wc-api/v3 (api doesn't work if I 301 Move it)
The other option is to allow both http and https to the entire site but if it is possible to exclude only the api request it would be wayy better!

Thanks in advance and appreciate your help :smile:

EDIT: found some ideas but don't know how to implement them:
1) Enforcing https for every url except those with api/wc-api keyword inside.
2) Fix it with a custom redirect
From:
Here's the nginx config:
Code:
server {
        listen 80 default_server;
        listen [::]:80 default_server;
        server_name xx.com www.xx.com;
        return 301 https://$server_name$request_uri;
}

server {
        listen 443 ssl http2 default_server;
        listen [::]:443 ssl http2 default_server;
        include snippets/ssl-params.conf;
        ...etc
 
Last edited:
tried this without luck :( (see below)
Also realized I had force ssl activated in my cdn so it was showing the "301 Moved Permanently" but still API can't run until /wc-api/v3 is forced to go thru http

Code:
server {
    listen 80;...

    location / { 
        return 301 https://$server_name$request_uri;
    }

    location /wc-api/ {} 
    # ...
}
server {
    listen 443;

    location /l/ { 
        return 301 http://$server_name$request_uri;
    }
    # ...
}
 
Hello Builders!

I'm facing an issue, an API needs to use http to run properly on my site and I'm forcing all my traffic to use HTTPS. I've done some modifications but still can't make it work. Before adding the redirect on /wc-api/, when I used curl http:// site .com/wc-api/v3 (the url that needs to use http to work) I always got 301 moved permanently; but now with the changes, I'm getting a 404 not found error, so there's something missing. Your help will be much appreciated. Thanks in advance!

Here's my nginx config:
Code:
fastcgi_cache_path /var/run/nginx-cache levels=1:2 keys_zone=WORDPRESS:100m inactive=60m;
    fastcgi_cache_key "$scheme$request_method$host$request_uri";
    fastcgi_cache_use_stale error timeout invalid_header http_500;
    fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
    server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name site.com www.site.com;
    location / {
    return 301 https://$server_name$request_uri;
    }
    location /wc-api/ {
    }
    }
    server {
    listen 443 ssl http2 default_server;
    listen [::]:443 ssl http2 default_server;
    include snippets/ssl-params.conf;

    client_max_body_size 256M;
    root /var/www/html;
    index index.php index.html;

    server_name site.com www.site.com;

    # this must be near the top to ensure auto-renewals work
    location ~ /.well-known {
            allow all;
    }

    set $skip_cache 0;

    if ($request_method = POST) {
            set $skip_cache 1;
    }

    if ($query_string != "") {
            set $skip_cache 1;
    if ($request_uri ~* "/wp-admin/|/xmlrpc.php|wp-.*.php|/feed/|index.php|sitemap(_index)?.xml") {
            set $skip_cache 1;
    }

    if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") {
            set $skip_cache 1;
    }

    autoindex off;

    location ~ /purge(/.*) {
            fastcgi_cache_purge WORDPRESS "$scheme$request_method$host$1";
    }
    location ~* ^.+\.(flv|pdf|avi|mov|mp3|wmv|m4v|webm|aac|ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|css|rss|atom|js|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|ex$
            expires max;
            log_not_found off;
            access_log off;
    }

    location / {
            try_files $uri $uri/ /index.php?$args;
    }

    location /wc-api/ {
            return 301 http://$server_name$request_uri;
    }

    location ~ \.php$ {
            include snippets/fastcgi-php.conf;
            fastcgi_pass unix:/run/php/php7.0-fpm.sock;
            fastcgi_cache_bypass $skip_cache;
            fastcgi_no_cache $skip_cache;
            fastcgi_cache WORDPRESS;
            fastcgi_cache_valid 60m;
            include fastcgi_params;
    }
    location ~* ^/wp-includes/.*(?<!(js/tinymce/wp-tinymce))\.php$ {
            internal;
    }

    location = /favicon.ico {
            log_not_found off;
            access_log off;
    }

    location = /robots.txt {
            access_log off;
            log_not_found off;
    }

    location = /wp-config.php {
            deny all;
    }

    location ~* /(?:uploads|files)/.*\.php$ {
            deny all;
    location ~* ^/wp-content/.*\.(txt|md|exe|sh|bak|inc|php|pot|po|mo|log|sql)$ {
            deny all;
    }

    location ~ /\.ht {
            deny all;
    }
    }
 
Ironically I was facing something similar trying to do a proxy_pass. That's where I came across "break" and "^~" that might help you. While I don't have the exact solution, I would try this in the :80 server block:

Code:
	server {
		listen 80 default_server;
		listen [::]:80 default_server;
		server_name site.com www.site.com;

		location ^~ /wc-api/ {
			#whatever has to be processed here
			#[..]
			break;
		}

		location / {
			return 301 https://$server_name$request_uri;
		}

	}

The "^~" ensures that the particular directive gets evaluated first. The "break" stops everything else afterwards from processing - including the redirect to https(ssl).

So essentially if something is accessing /wc-api/ it will get processed in http, but everything else will get redirected automatically to https versions. Otherwise you'll be doing forever loops in the previous setup. I'd also remove the /wc-api/ block in the 443 server block.
 
Thanks, @CCarter works similar, I no longer have the 301 moved permanently error, instead i'm still getting a 404 not found (see below) The third post in this thread has all my nginx site config
Code:
# curl http://site.com/wc-api/v3
<html>
<head><title>404 Not Found</title></head>
<body bgcolor="white">
<center><h1>404 Not Found</h1></center>
<hr><center>nginx</center>
</body>
</html>
 
Last edited:
The third post in this thread has all my nginx site config
Is the api script actually live at the location without errors? Meaning can you execute it from the command line? Is it a php script? You'll have to put something to tell the system what should be running in the /wc-api/, like for a php outout:

Code:
try_files $uri $uri/ /index.php?$args;

Can you place an index.html file with random text and then visit it to make sure it's rendering correctly?

Look in your nginx access.log and error logs by using the commandline and doing something like:

Code:
cat /var/log/nginx/access.log | grep "/wc-api"

To see if it is being accessed, and then try it with the error.log in place of access.log to see what's going on there. If there is a true error it should be there. You can then try do:

Code:
tail -f /var/log/nginx/error.log | grep "/wc-api"

And attempt to go to the /wc-api/ url in your browser and see the error output in real time and fix it from there.
 
@CCarter Thanks for your help; yes, the script has no errors;
When I add this in :80 section I get the 301 moved message again (and it's not supposed to do that anymore right?)
Code:
location ^~ /wc-api/ {
        try_files $uri $uri/ /index.php?$args;
        break;
        }

I just changed the nginx config and allowed http and https traffic to the site (I prefer to not have to but I kept getting the 404 error :mad: ), works great when I changed it to:

Code:
server {
        listen 80 default_server;
        listen [::]:80 default_server;
        listen 443 ssl http2 default_server;
        listen [::]:443 ssl http2 default_server;

        server_name site.com www.site.com;
        include snippets/ssl-params.conf;

        client_max_body_size 256M;
        root /var/www/html;
        index index.php index.html;

        # this must be near the top to ensure auto-renewals work
        location ~ /.well-known {
                allow all;
        }
 [...] THE REST

But allowing both http and https is not really recommended if it can be avoided (what I'm trying to do)
There's a missing piece in the previous config that makes the 404 error :(
 
The 404 error might be happening because your permalinks are not set to "post name". It's a woocommerce bug/error. If you google "wc-api" the number one auto-suggest is "wc-api 404", so it's wc-api that might be the problem.

Try going back to the original separate :80 and :443 solution fro above and changing the permalink to "post name". If that works then it's we-api that's the problem. Check out this post: http://stackoverflow.com/questions/22710078/woocommerce-rest-api-404-error
 
The 404 error might be happening because your permalinks are not set to "post name". It's a woocommerce bug/error. If you google "wc-api" the number one auto-suggest is "wc-api 404", so it's wc-api that might be the problem.

Try going back to the original separate :80 and :443 solution fro above and changing the permalink to "post name". If that works then it's we-api that's the problem. Check out this post: http://stackoverflow.com/questions/22710078/woocommerce-rest-api-404-error

Yes seems like there's a woocommerce error with wc-api, but my permalinks are set to Post name, just updated them just in case and the issue was still there. Maybe I need to update AllowOverride as the second answer said or something similar for it to work because it's a nginx server and doesn't have apache?? How can I do that?
 
Last edited:
AllowOverride as the second answer

There is no AllowOverride command, but you try "passenger_enabled on;" (Sauce: http://stackoverflow.com/questions/35705641/how-to-convert-apaches-allowoverride-all-to-nginx)

What error is coming up when you grep the "/wc-api/" using cat or tail? That should tell you exactly or close to what's wrong. I'm also signal @SmokeTree for this one. You might need someone to take a closer look cause the problem it's getting specific to your setup.
 
These are the errors coming using cat and tail:
Code:
1) ~# cat /var/log/nginx/access.log | grep "/wc-api"
[x.y.z.a] - ck_[key] [19/Mar/2017:10:02:5                                         8 -0400] "GET /wc-api/v2/coupons?consumer_key=ck_[ck]                                        [num]&consumer_secret=cs_[cs] HTTP/1.1"                                          401 107 "-" "node-woocommerce/2.4.0"
Binary file (standard input) matches
2) ~# tail -f /var/log/nginx/error.log | grep "/wc-api"
2017/03/20 13:16:24 [error] 3589#3589: *12 open() "/usr/share/nginx/html/wc-api/v3" failed (2: No such file or directory), client: [...], server: site.com, request: "GET /wc-api/v3 HTTP/1.1", host: "site.com"
2017/03/20 13:17:01 [error] 3589#3589: *22 open() "/usr/share/nginx/html/wc-api/v3" failed (2: No such file or directory), client: [...], server: site.com, request: "GET /wc-api/v3 HTTP/1.1", host: "site.com"
2017/03/20 13:18:37 [error] 3589#3589: *42 open() "/usr/share/nginx/html/wc-api/v3" failed (2: No such file or directory), client: [...], server: site.com, request: "GET /wc-api/v3 HTTP/1.1", host: "site.com"
2017/03/20 13:20:10 [error] 3589#3589: *58 open() "/usr/share/nginx/html/wc-api/v3" failed (2: No such file or directory), client: [...], server: site.com, request: "GET /wc-api/v3 HTTP/1.1", host: "site.com"
2017/03/20 13:20:42 [error] 3589#3589: *71 open() "/usr/share/nginx/html/wc-api/v3" failed (2: No such file or directory), client: [...], server: site.com, request: "GET /wc-api/v3 HTTP/1.1", host: "site.com"
2017/03/20 13:20:50 [error] 3589#3589: *72 open() "/usr/share/nginx/html/wc-api/v2" failed (2: No such file or directory), client: [...], server: site.com, request: "GET /wc-api/v2 HTTP/1.1", host: "site.com"
2017/03/20 13:20:54 [error] 3589#3589: *73 open() "/usr/share/nginx/html/wc-api/v3" failed (2: No such file or directory), client: [...], server: site.com, request: "GET /wc-api/v3 HTTP/1.1", host: "site.com"
2017/03/20 13:46:08 [error] 3589#3589: *212 open() "/usr/share/nginx/html/wc-api/v3" failed (2: No such file or directory), client: [...], server: site.com, request: "GET /wc-api/v3 HTTP/1.1", host: "site.com"

HTTP/1.1 has something to do with my gzip?
Code:
gzip on;
        gzip_disable "msie6";

        gzip_vary on;
        gzip_proxied any;
        gzip_comp_level 6;
        gzip_buffers 16 8k;
        gzip_http_version 1.1;
        gzip_types
            application/atom+xml
            application/javascript
            application/json
            application/rss+xml
            application/vnd.ms-fontobject
            application/x-font-ttf
            application/x-javascript
            application/x-web-app-manifest+json
            application/xhtml+xml
            application/xml
            font/opentype
            image/svg+xml
            image/x-icon
            text/css
            text/plain
            text/x-component
            text/xml
            text/javascript;
EDIT: guess not because when I deleted gzip_http_version 1.1; the error was still there
 
Your error shows the system looking for a file in /usr/share/nginx/html/wc-api/v3 which, from the initial path of /usr/share/nginx I'm assuming a CentOS install. Your root on your config shows the default Ubuntu path of /var/www/html. I'd start by looking at that. Also, make sure the file permissions are correct for any Files/Folders. The Site Security & Online Privacy article I wrote for our highly recommend digital strategy crash course goes into that.

Regarding Nginx vs Apache. Nginx doesn't have an .htaccess file and honestly, that's a VERY good thing. .htaccess is horrible for performance and always has been. On Apache, it's best to put all the stuff that would normally be in .htaccess in the vhost config. In Nginx, you can do pretty much everything you would need .htaccess for, it's just a bit different and you put it all into the vhost config.

Hope this helps :smile:
 
Regarding Nginx vs Apache. Nginx doesn't have an .htaccess file and honestly, that's a VERY good thing. .htaccess is horrible for performance and always has been. On Apache, it's best to put all the stuff that would normally be in .htaccess in the vhost config. In Nginx, you can do pretty much everything you would need .htaccess for, it's just a bit different and you put it all into the vhost config.

Double that. Apache has to parse your .htaccess files in your directories on each request. Terribly wasteful. I would guess it is not common knowledge because you see it everywhere!
 
Your error shows the system looking for a file in /usr/share/nginx/html/wc-api/v3 which, from the initial path of /usr/share/nginx I'm assuming a CentOS install. Your root on your config shows the default Ubuntu path of /var/www/html.

@SmokeTree Thanks for your reply, I just checked and there's nothing on /usr/share/nginx/html/ as is supposed. I don't know why it is calling there, Never installed or touched CentOS.
Also my file permision are correct: 755 for directory and 644 for files

Keep in mind that when I allow traffic from http and https the API works great without errors:
Code:
server {
        listen 80 default_server;
        listen [::]:80 default_server;
        listen 443 ssl http2 default_server;
        listen [::]:443 ssl http2 default_server;

        server_name site.com www.site.com;
        include snippets/ssl-params.conf;

        client_max_body_size 256M;
        root /var/www/html;
        index index.php index.html;

       [...] THE REST

So only when I do the redirect it messes somehow with the path to nothing

There are no errors when I use cat and tail before adding the location redirect but when I add the redirect it shows that the path is wrong as you said:

How could I correct/change it? Thanks again!

Code:
1) cat /var/log/nginx/error.log | grep "/wc-api"
2017/03/20 15:59:08 [error] 6007#6007: *7 open() "/usr/share/nginx/html/wc-api/v3" failed (2: No such file or directory), client: [], server: site.com, request: "GET /wc-api/v3 HTTP/1.1", host: "site.com"
2) tail -f /var/log/nginx/error.log | grep "/wc-api"
2017/03/20 15:59:08 [error] 6007#6007: *7 open() "/usr/share/nginx/html/wc-api/v3" failed (2: No such file or directory), client: [], server: site.com, request: "GET /wc-api/v3 HTTP/1.1", host: "site.com"
 
To start, try adding this to your server{} block for port 80:

root /var/www/html;

You're telling the 443 block where to find the files but since you're needing to access the files with port 80, you need to tell it where to find those files, and that's probably why it's just going off into the horizon and looking for the "default" root dir. Each "server" block needs to be told exactly how to handle the files it's going to process. In short, they are separate and don't really know about each other or inherit from each other. Let me know what happens.
 
@SmokeTree Yes, I just thought that could happen because there was not root directive, but I kept getting the error because there isn't a html/wc-api directory

is there a way to call a url?? like root or something site.com/wc-api ???

2017/03/20 16:51:44 [error] 5138#5138: *10 open() "/var/www/html/wc-api/v3" failed (2: No such file or directory), client: [], server: site.com, request: "GET /wc-api/v3 HTTP/1.1", host: "site.com"
 
Wait a minute, wait a minute. Is "/wc-api" a plugin or a physical file like index.php inside the root directory like "/var/www/html/wc-api/v3/index.php"? Cause if it's just a wordpress plugin then it's called through Wordpress's index.php and there is no physical file in that directory.
 
is there a way to call a url?? like root or something site.com/wc-api

Not sure what you mean. One question. From the looks of it, this sounds like the WooCommerce REST API (Found your StackOverflow post related to this BTW :smile: ). I'm not really a WP expert (I can help get you off that stuff though) but I'm looking here and it looks like the whole thing can be done over https: https://woocommerce.github.io/woocommerce-rest-api-docs/v3.html#introduction Where are you seeing that you have to use http?
 
Wait a minute, wait a minute. Is "/wc-api" a plugin or a physical file like index.php inside the root directory like "/var/www/html/wc-api/v3/index.php"? Cause if it's just a wordpress plugin then it's called through Wordpress's index.php and there is no physical file in that directory.

Is a woocommerce rest api that should allow a third party app to work, it also shows the following when i curl it and works:
Code:
{"store":{"name":"Site","description":"","URL":"https:\/\/site.com","wc_version":"2.6.14","version":"3.1.0","routes":{"\/":{"supports":["HEAD","GET"],"meta":{"self":"https:\/\/site.com\/wc-api\/v3\/"}},"\/coupons":{"supports":["HEAD","GET","POST"],"meta":{"se
-- [MORE] --
timezone":"America\/New_York","currency":"USD","currency_format":"","currency_position":"left","thousand_separator":",","decimal_separator":".","price_num_decimals":2,"tax_included":false,"weight_unit":"lbs","dimension_unit":"in","ssl_enabled":true,"permalinks_enabled":true,"generate_password":false,"links":{"help":"https:\/\/woothemes.github.io\/woocommerce-rest-api-docs\/"}}}}

Not sure what you mean. One question. From the looks of it, this sounds like the WooCommerce REST API (Found your StackOverflow post related to this BTW :smile: ). I'm not really a WP expert (I can help get you off that stuff though) but I'm looking here and it looks like the whole thing can be done over https: https://woocommerce.github.io/woocommerce-rest-api-docs/v3.html#introduction Where are you seeing that you have to use http?

lol, I've been asking all over the world how to solve the 404 error!
Yea most apps use https, I can access wc-api/v3 using https but the app can't (my third-party app only allows http for the moment), they just sent me this e-mail:
dev mentioned that sites are using https on their sites. He is planning to code to account for that so we don't have to create these sorts of exceptions. (He is refering to the fact that the app doesn't work on https yet)
He asked if you want to BETA test with https
I just want to start selling :tongue:
 
Last edited:
Is a woocommerce rest api for a third party app that shows the following when i curl it and works:
When you FTP into the folder "/var/www/html/wc-api/" or "/var/www/html/wc-api/v3" are there actual files in that folder? The solutions we are giving you assumes the folder "/wc-api/" actually exists inside the /html subdirectory and isn't a plugin that needs wordpress to run. Curl doesn't answer the question - cause of redirects and rewrites.

When you go into the folder "/var/www/html/wc-api/" can you do the command "ls" to get a list of the files in that directory? If not, can you go up one directory and do the command "ls" command within "/var/www/html/"? Does it list the folder /wc-api/ alongside /wp-content/, /wp-admin/, and /wp-includes/?

To quickly figure it out you can do the following command from anywhere on the commandline:
Code:
ls /var/www/html/wc-api/
and then try
Code:
ls /var/www/html/

to see if the wc-api actually is real or just a result of a rewrite.
 
Yes I'd definitely take them up on the https beta test offer. In general, it's really not a good idea to mix http and https. Don't worry about the use of the word BETA. All software is Beta, just in different stages of stability. It won't be long before browsers accept only https. http is on its way to deprecation, sans some reverse proxy type things.
 
Last edited:
When you FTP into the folder "/var/www/html/wc-api/" or "/var/www/html/wc-api/v3" are there actual files in that folder? The solutions we are giving you assumes the folder "/wc-api/" actually exists inside the /html subdirectory and isn't a plugin that needs wordpress to run. Curl doesn't answer the question - cause of redirects and rewrites.
no, there isn't a wc-api folder but there is a site.com/wc-api/v3 that exists it allows a rest api request to the site I suppose.
Code:
ls /var/www/html/wc-api/
ls: cannot access '/var/www/html/wc-api/': No such file or directory
# ls /var/www/html/
index.nginx-debian.html  wp-comments-post.php  wp-load.php
index.php                wp-config.php         wp-login.php
license.txt              wp-config-sample.php  wp-mail.php
readme.html              wp-content            wp-settings.php
wp-activate.php          wp-cron.php           wp-signup.php
wp-admin                 wp-includes           wp-trackback.php
wp-blog-header.php       wp-links-opml.php     xmlrpc.php

Yes I'd definitely take them up on the https beta test offer. In general, it's really not a good idea to mix http and https. Don't worry about the use of the word BETA. All software is Beta, just in different stages of stability. It won't be long before browsers only accept only https. http is on its way to deprecation, sans some reverse proxy type things.

Yes, just told them I could help, should work properly on https really soon if they're serious (which I think they are)
 
there isn't a wc-api folder

It doesn't really "exist" though, it's a result of a rewrite. But this solves the problem. What you want is a bit tricky since there is no actual /wc-api/ folder or files inside to process your request, that means wordpress is handling it as a redirect. That's why when the code was setup to exclude for SSL the /wc-api/ folder it was coming back as a 404, since it was literally looking for that folder and whatever was in there needs to be proccessed.

This is an interesting dilemma, but the solution can be to use the code that breaks the SSL for /wc-api/ and then hard code php to process the wordpress's index.php for anything inside that folder.
Code:
    server {
        listen 80 default_server;
        listen [::]:80 default_server;
        server_name site.com www.site.com;

        location ^~ /wc-api/ {

                fastcgi_pass unix:/run/php/php7.0-fpm.sock;
                fastcgi_index index.php;
                fastcgi_param SCRIPT_FILENAME $document_root/index.php?$args;
                #fastcgi_param SCRIPT_FILENAME /var/www/html/index.php?$args;
                include fastcgi_params;
            break;
        }

        location / {
            return 301 https://$server_name$request_uri;
        }

    }

^^ Something along those lines where the actual wordpress' root index.php is hardcoded, I used $document_root, but left commented out the "/var/www/html/" hardcoded version just in case you need to use that and comment out the $document_root.

The theory is when something requests the /wc-api/ folder wordpress's index.php will process that. Now another problem you might encounter, is wordpress's index.php might switch it to https cause your site's wordpress install is defaulting to SSL. you might have to go into your wordpress settings, change the two instances of your website to http from https, and then just let nginx handle the switch to SSL.
 
This is an interesting dilemma, but the solution can be to use the code that breaks the SSL for /wc-api/ and then hard code php to process the wordpress's index.php for anything inside that folder.
Wow, seems it is way more complicated than I thought, but I get a file not found error when I try it; maybe because I should change SCRIPT_FILENAME for the real name(really no idea which is)

19:06:09 [error] 5297#5297: *1 FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream, client: [], server: site.com, request: "GET /wc-api/v3 HTTP/1.1", upstream: "fastcgi://unix:/run/php/php7.0-fpm.sock:", host: "site.com"
 
Back