12

I am setting up WooCommerce to trigger a webhook upon order creation. I have set the webhook's URL as the url of a local web API we have setup for this purpose:

http://localhost:3000/store/orders/new

WooCommerce does trigger the webhook with the correct data payload, but the request is reported as failed in the webhook's logs:

Status: HTTP http_request_failed Es wurde keine gültige URL übermittelt.: Array

which, translated from German, means "no valid URL was passed"

I then later changed the URL to a web-facing deployment of our API (https://xxx.azurewebsites.net/store/order/new), and the webhook was received without any problems by the API.

I am not sure if WC webhook's don't play nice with urls that have a custom port (in my case, port 3000), so I wanted to ask the question on whether this is true and if there is a way to make WC webhooks play nice with a localhost development environment.

Luis Delgado
  • 3,644
  • 4
  • 34
  • 54

7 Answers7

11

I solved it after inserting the following code at the end of the file: wp-content/themes/MYTHEME/functions.php

function allow_unsafe_urls ( $args ) {
       $args['reject_unsafe_urls'] = false;
       return $args;
    } ;

add_filter( 'http_request_args', 'allow_unsafe_urls' );
Flavio Troia
  • 2,451
  • 1
  • 25
  • 27
  • 4
    This should be the accepted answer since no modifications on wp core are needed and the filter "http_request_host_is_external" does not work for none default ports. Thank you Flavio – Niko Hadouken Nov 21 '21 at 18:47
  • This is the best answer for the reason given by @NikoHadouken above. I'd like to add that you shouldn't edit the `functions.php` that comes with your theme - rather use the [plugin customiser tool](https://github.com/woocommerce/theme-customisations) from WooThemes – Tian van Heerden Feb 02 '22 at 10:07
8

For WooCommerce version 3.3.5, Bjorn's solution doesn't seem to work.

In my case, I had to eddit the file wp-content/plugins/woocommerce/includes/class-wc-webhook.php:185, method deliver.

Comment the wp_safe_remote_request method, and instead, use the insecure http request method.

// Webhook away!
$http_call = _wp_http_get_object();
$response = $http_call->request( $this->get_delivery_url(), $http_args );
//$response = wp_safe_remote_request( $this->get_delivery_url(), $http_args );
tokenizer_fsj
  • 1,130
  • 13
  • 18
6

It is not the custom port, but localhost.

There is a check in wp-includes/http.php wp_http_validate_url() that rejects all kinds of local IPs unless specifically allowed with a filter on http_request_host_is_external that returns true...

Cheers, Björn

Björn
  • 61
  • 2
  • awesome! you just made my day! – GETah Dec 06 '15 at 13:19
  • 3
    Really great, but there seems to be an issue with ports too. There's a check in that method: `if ( 80 === $port || 443 === $port || 8080 === $port )`, so it only supports common port numbers. – Aron Lorincz Jul 06 '16 at 20:05
3

in the following function

/** * Validate a URL for safe use in the HTTP API. * * @since 3.5.2 * * @param string $url * @return false|string URL or false on failure. */

comment this line

if ( isset( $parsed_home['host'] ) ) {
        //$same_host = ( strtolower( $parsed_home['host'] ) === strtolower( $parsed_url['host'] ) || 'localhost' === strtolower( $parsed_url['host'] ) );
        $same_host = false;
    } else {
        $same_host = false;
    }

and if you're using another port for example in laravel you have to add the port here

if ( empty( $parsed_url['port'] ) )
        return $url;

    $port = $parsed_url['port'];
    if ( 80 === $port || 443 === $port || 8080 === $port || 8000 === $port )
        return $url;

    if ( $parsed_home && $same_host && isset( $parsed_home['port'] ) && $parsed_home['port'] === $port )
        return $url;

    return false;
}
Jose Ramirez
  • 69
  • 1
  • 6
0

If anyone is still looking for an answer to this, my solution was to make an A DNS record pointing to the server that receives the WebHook and then only allow internal traffic on the firewall.

Steps using DigitalOcean's VPC + Firewall and Cloudflare:

  1. Log in to CloudFlare, Create an A record pointing to the server's public IP
  2. On DigitalOcean's panel go to the firewall and only allow traffic from the origin server (or tag)
  3. Setup the webhook as usual on WooCommerce.

Felipe

0

What worked for me:

  1. In class-http.php, change
'reject_unsafe_urls'  => apply_filters( 'http_request_reject_unsafe_urls', false, $url ),

to

'reject_unsafe_urls'  => apply_filters( 'http_request_reject_unsafe_urls', true, $url ),
  1. In http.php, add your port in this line (I added port 3000 for this example)
if ( 80 === $port || 443 === $port || 8080 === $port || 3000 === $port ) {

Works in WooCommerce 4.2.2

Bob
  • 37
  • 1
  • 7
0

Wordpress http request may be blocking certain ports and hosts. However, I can confirm that querying aganinst localhost:8080 would work.

On the other hand, you could also modify the http.php in order to extend the number of valid ports

Alberto S.
  • 1,805
  • 23
  • 39