karatelabs / karate

Test Automation Made Simple
https://karatelabs.github.io/karate
MIT License
8.27k stars 1.95k forks source link

Pass-through proxy functionality of karate mock server is broken #2048

Closed ismail-s closed 2 years ago

ismail-s commented 2 years ago

Summary

The pass-through proxy functionality of karate mock server is broken with Armeria dep >=1.10 .

Steps to reproduce

(sorry in advance, I didn't use the starter project for these steps. But I've tried to make the steps v simple anyway)

  1. Create a feature file (called e.g. test.feature) with these contents (yes, I did just hack an example file from the repo, hence the payments references):

    Feature: payment service proxy (or api-gateway !)
    
    Scenario: pathMatches('/payments')
        Then def response = "This is a test"
    
    # 'catch-all' rule
    Scenario:  
        # if arg to karate.proceed() is null, incoming url will be used as-is (http proxy)
        * karate.proceed()
  2. Download the Karate fatjar (any v1.2.x release)
  3. In one terminal, run the command java -jar ./karate-1.2.1.RC1.jar -m test.feature (change for the version of the fatjar used)
  4. In another terminal, run the command curl -x http://localhost:8080 http://neverssl.com

Expected behaviour

The curl command prints the html response body of http://neverssl.com

Actual behaviour

Curl prints:

400 Bad Request
Invalid request path

and karate doesn't print any output when this curl command is run.

Additional info

I tried changing the version of the armeria dep (in karate-core/pom.xml) to different versions, and found that as long as the armeria version was >=1.10.0, that this bug occurred.

A temporary workaround is to selectively downgrade armeria to e.g. v1.9.0 or earlier.

ismail-s commented 2 years ago

Also, looking at a6174b454e30d14731c4d9d1c1f96c0006a69f80, perhaps this issue was noticed when the dep was upgraded.

ptrthomas commented 2 years ago

@ismail-s thanks for the investigation. tagging as help wanted, not something I consider priority

ptrthomas commented 2 years ago

moving to project board: https://github.com/karatelabs/karate/projects/3#card-84764655

ismail-s commented 1 year ago

FYI I've taken another look at this whilst trying to upgrade to Karate 1.4. I've found that in armeria v1.23 release notes, it says:

You can now handle an HTTP/1 request with an absolute URI using ServerBuilder.absoluteUriTransformer(). #4681 #4726

I've investigated this and have found that if I take karate/core/MockServer.java, and do something like this change:

            ServerBuilder sb = Server.builder();
+           sb.absoluteUriTransformer(absoluteUri -> {
+               return absoluteUri.replaceFirst("^http://[^/]+/", "/");
+           });
            sb.requestTimeoutMillis(0);

then the pass-through proxy functionality starts to work again. I'm not fully sure of the impacts of this change (e.g. this may stop the domain getting through to the mock feature file), whether it conflicts with other things in Karate, but for the pass-through proxy functionality, it seems to fix the issue for us.

Also FYI (if it's useful or just of interest): we're using the pass-through proxy functionality with chromedriver, with tests running in parallel (using the neat parallel support Karate has)

Also, if you're interested, I think we also hit #2329 as in our mock feature file, we were calling a JS function (defined in its own .js file). I found I had to inline the JS function in the mock feature file and turn it into Karate syntax to get it to work. I'm fairly certain the issue we hit here was some sort of locking like mentioned in #2329 because after our test had gone near the end, then suddenly the mock server would start responding again, as if it had hit a lock and got blocked until then.

ptrthomas commented 1 year ago

@ismail-s thanks for sharing and much appreciated. js functions are troublesome, so if you really need a lock-free option, consider using a java method (static or otherwise), as you may have seen in my comment in #2329