Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot perform GET requests to local apache webserver setup with VirtualDocumentRoot #150

Closed
mmenozzi opened this issue Nov 27, 2017 · 14 comments

Comments

@mmenozzi
Copy link

Hi guys,
I have a problem similar to the issue #138 but it happens in a very weird manner so I don't think is related to that issue but the error message is the same: Socket disconnected prior to response completion (Parser state: 0). I'll explain the whole story.

I have a Mac Book Pro as a development machine and I have a simply Apache + PHP + MySQL setup. I have to work on several projects so to speedup the setup of every new project I configured Apache with VirtualDocumentRoot directive (here an example of my configuration http://roberto-montero.com/blog/how-setup-xampp-use-virtualdocumentroot-mac-os-x). I have also a virtual host configured for localhost whose document root is the root of my workspace (the directory which contains all of my projects, ~/Work/Projects).
So if go to http://localhost/phpinfo.php, I get the phpinfo located in the root of all my projects (~/Work/Projects/phpinfo.php). Instead if I go to http://myproject.dev/phpinfo.php I get the phpinfo located in the directory of "myproject" (~/Work/Projects/myproject/phpinfo.php).

Ok, given this scenario, I wanted to use this async HTTP client to perform HTTP requests against a project which I'm working on.

So I installed artax using composer and simply copy & pasted your example n. 1 (https://github.com/amphp/artax/blob/master/examples/1-get-request.php) to perform a simple GET request.

First I tried with the URL provided in the example (https://httpbin.org/user-agent) and it worked.
But then, I tried with my local project using the URL http://myproject.dev/phpinfo.php, and this last trial didn't work. I got the error Socket disconnected prior to response completion (Parser state: 0).
After several trials I figured out that if I use http://localhost/phpinfo.php it works. So I tried with several different request to other resources/projects and the pattern that I found is that:

  • Requests to resources under http://localhost/ are working
  • Requests to resources under VirtualDocumentRoot virtual hosts (like http://myproject.dev/) are not working.

Please note that all of them are served from my dev machine (so Apache is the same, PHP is the same, etc...) and all my trials are with the same sample script.

So it seems (but I would like to confirm) that there is some weird circumstance that cause that error only if use a VirtualDocumentRoot virtual host.

Now, I would like to understand what the f**k is going on but I have no idea where to start. Do you guys have any suggestion? 😄

Thank you.

@kelunik
Copy link
Member

kelunik commented Nov 27, 2017

If you use another HTTP client it works perfectly fine I guess (other than your browser)?

Do you have HTTPS configured? If you're using Chrome, it might automatically use HTTPS, see https://ma.ttias.be/chrome-force-dev-domains-https-via-preloaded-hsts/. You should probably move your development off of .dev.

@staabm
Copy link
Member

staabm commented Nov 27, 2017

Does artax send a HTTP_HOST header?

@kelunik
Copy link
Member

kelunik commented Nov 27, 2017

@staabm Yes, of course.

@mmenozzi
Copy link
Author

Hi @kelunik,
yes with other HTTP clients it works perfectly fine. I tried with, wget, curl and httpie, for all of them both the localhost and myproject.dev work as expected.

Anyway I have an interesting update. If I add the 127.0.0.1 myproject.dev entry to my /etc/hosts file, it works! So is something related to the DNS resolution...

I'm gonna do some other investigation, I'll keep you up to date.

@staabm
Copy link
Member

staabm commented Nov 28, 2017

@mmenozzi could you use some debugging switches (or a http proxy) or similar to compare the http traffic of artax with one of the working clients?

@kelunik
Copy link
Member

kelunik commented Nov 28, 2017

@staabm Not necessary, it's the DNS resolution then.

@mmenozzi We use a custom DNS resolver, because the system-provided APIs are blocking and thus unsuited. How does your myproject.dev usually get resolved if not via /etc/hosts? Do you have a local DNS server that does that? Is that local DNS server listed in /etc/resolv.conf?

@mmenozzi
Copy link
Author

mmenozzi commented Nov 28, 2017

Ok @kelunik I see the custom DNS resolver. I use dnsmasq to resolve *.dev to 127.0.0.1.
These are the uncommented directives in the dnsmasq configuration file /usr/local/etc/dnsmasq.conf:

no-resolv
no-poll

server=127.0.0.1#53
server=8.8.8.8
server=8.8.4.4

address=/dev/127.0.0.1

listen-address=127.0.0.1
bind-interfaces

log-queries
log-facility=/tmp/dnsmasq.log

This is my /etc/resolv.conf file:

#
# macOS Notice
#
# This file is not consulted for DNS hostname resolution, address
# resolution, or the DNS query routing mechanism used by most
# processes on this system.
#
# To view the DNS configuration used by this system, use:
#   scutil --dns
#
# SEE ALSO
#   dns-sd(1), scutil(8)
#
# This file is automatically generated.
#
nameserver 8.8.8.8

But I also have the file /etc/resolver/dev with the following content:

nameserver 127.0.0.1

To investigate further I created the following test script:

<?php
use Amp\Loop;
require __DIR__ . '/vendor/autoload.php';
Loop::run(function () {
    $ip = yield \Amp\Dns\resolve('myproject.dev');
    var_dump($ip);
});

and the output is:

array(1) {
  [0]=>
  object(Amp\Dns\Record)#159 (3) {
    ["value":"Amp\Dns\Record":private]=>
    string(11) "127.0.53.53"
    ["type":"Amp\Dns\Record":private]=>
    int(1)
    ["ttl":"Amp\Dns\Record":private]=>
    int(3599)
  }
}

With the same script, if I put the entry into /etc/hosts, the output is:

array(1) {
  [0]=>
  object(Amp\Dns\Record)#20 (3) {
    ["value":"Amp\Dns\Record":private]=>
    string(9) "127.0.0.1"
    ["type":"Amp\Dns\Record":private]=>
    int(1)
    ["ttl":"Amp\Dns\Record":private]=>
    NULL
  }
}

But in both ways the output of the ping myproject.dev command is always:

PING myproject.dev (127.0.0.1): 56 data bytes
64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.029 ms
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.076 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.093 ms
64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.058 ms
^C
--- myproject.dev ping statistics ---
4 packets transmitted, 4 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 0.029/0.064/0.093/0.024 ms

and in both ways the output of the php -r "echo gethostbyname('myproject.dev');" is always 127.0.0.1.

@kelunik
Copy link
Member

kelunik commented Nov 28, 2017

How does your system resolver find /etc/resolver/dev? We currently only have a look at /etc/hosts and /etc/resolv.conf. If you change your /etc/resolv.conf to use nameserver 127.0.0.1, it should work just fine.

@mmenozzi
Copy link
Author

I have no idea @kelunik. I have to investigate. I'll keep you up to date.

@mmenozzi
Copy link
Author

Hi @kelunik,
I did a quick research on that and the only "official" thing I found is this Apple man page: https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man5/resolver.5.html

At the SEARCH STRATEGY section they say:

The configuration for a particular client may be read from a file having the format described in this
man page. These are at present located by the system in the /etc/resolv.conf file and in the files
found in the /etc/resolver directory. However, client configurations are not limited to file storage.
The implementation of the DNS multi-client search strategy may also locate client configuratins in
other data sources, such as the System Configuration Database. Users of the DNS system should make no
assumptions about the source of the configuration data.

So I think that the macOS DNS resolver looks up for files in the /etc/resolver directory to get the nameserver to use for a particular host name.

If you think it's worth it, the amphp/dns component should be fixed to support this resolve strategy.

Otherwise I think it's perfectly fine to assume that amphp/dns supports only a basic resolve strategy based on /etc/resolv.conf and /etc/hosts files (maybe it should be stated in the documentation).

Feel free to close this issue.
Bye!

@kelunik
Copy link
Member

kelunik commented Nov 28, 2017

Have you manually configured it to use /etc/resolver/dev or did some tool automate this? If it's a done by a tool it might be more common and should be fixed.

@amphp/dns opinions?

@mmenozzi
Copy link
Author

No I didn't configured it. I just followed an online tutorial like this: https://www.fourkitchens.com/blog/article/local-development-apache-vhosts-and-dnsmasq/

From what I understand it's the builtin behavior of the macOS's resolver, it looks for files inside /etc/resolver before falling back to /etc/resolve.conf

@kelunik
Copy link
Member

kelunik commented Dec 25, 2017

@mmenozzi I'm going to close this issue here. Could you open an appropriate issue for amphp/dns please with a summary?

@mmenozzi
Copy link
Author

Done: amphp/dns#69

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants