guzzle / guzzle

Guzzle, an extensible PHP HTTP client
https://docs.guzzlephp.org/
MIT License
23.13k stars 2.4k forks source link

How to cancel url-encode in query? #1758

Closed blsn closed 7 years ago

blsn commented 7 years ago

I need to cancel url-encode the "=" character in ClientName=John

API doc: http://api.wordbee-translator.com:32570/projects?token=xxx&filter=ClientName='John'

The GET Method that I use to implement with filter:

$resp = $project->request('GET', 'projects', [
        'query' => [
            'token' => $tokenId,
            'filter' => 'ClientName=John'
        ]
]);

I get response '400 Bad Request' due to the %3D characters as appears below: https://api.wordbee-translator.com:32570/projects?token=xxx&filter=ClientName%3DJohn

How to fix it?

Konafets commented 7 years ago

You don't send John as a String to the API: &filter=ClientName='John' vs 'filter' => 'ClientName=John'. Mind the missing '' around John

blsn commented 7 years ago

Thank you for your comment, I still get the same error. The issue is how to cancel url-encode the "=" character.

For example I tried the following: 'filter=ProjectId' => 77 uri result: https://api.wordbee-translator.com:32570/projects?token=xxx&filter%3DProjectId=77

And I tried the following:

'filter' => [       
   'ProjectId' => 77    
] 

uri result: https://api.wordbee-translator.com:32570/projects?token=xxx&filter%5BProjectId%5D=77

How to get the effective uri as follows? https://api.wordbee-translator.com:32570/projects?token=xxx&filter=ProjectId=77

sagikazarmark commented 7 years ago

This is a duplicate of https://github.com/guzzle/guzzle/issues/1696#issuecomment-280092334

Please check the answer there.

ValeriiTsarov commented 7 years ago

One more question.

How can I use this query and cancel urlencode symbols : " (quote) in a request? ['query' => ['Query' => Gtin:"027917022710"]]

Guzzle transformates it to ?Query=Gtin%3A%22648575210037%22

sagikazarmark commented 7 years ago

You can't, it's intended. You have to decode it on the receiver side.

rafapaulin commented 6 years ago

Intended, but sometimes we are using 3rd party apis which does not do the decode... how to solve the encoding in that case?

drtechie commented 6 years ago

There must be some option to prevent URL encoding of the query string.

The issue I am facing is as follows.

       $paramsJoined = array();

        foreach($api_details['query'] as $param => $value) {
            $paramsJoined[] = "$param=$value";
        }

        $query = implode('&', $paramsJoined);

        $response = $client->get($api_details['url'], [
            'query' => $query,
            'on_stats' => function (TransferStats $stats) use (&$url) {
                $url = $stats->getEffectiveUri();
            }
        ]);
...

'url' => Config::get('apiURL'),
'query' => array(
     'q' => $search_string.' AND prism.creationDate>='.$created_date,
     'maximumRecords' => 100,
      'httpAccept' => 'application/json'
)

...

The actual query that I need

q=keyword AND prism.creationDate>=2017

What Guzzle's effective URI is

q=keyword%2520AND%2520prism.creationDate%253E%3D2017

Expected

q=keyword%20AND%20prism.creationDate%3E%3D2017

What I have tried

Passing the array (instead of joined params). Appending '?'.$query Keeping the encoded string -> this results in characters like % getting encoded again.

tomsihap commented 5 years ago

Any updates about this issue ?

kalesh13 commented 5 years ago

Looks like I can't use Guzzle for Paypal API calls.

https://developer.paypal.com/docs/classic/payflow/integration-guide/#do-not-url-encode-name-value-parameter-data

There should be some option to disable url encoding.

gseidel commented 4 years ago

There is a workaround. The Problem is the GuzzleHttp\Psr7\Uri class which apply the encoding to the URI. Since GuzzleHttp\Psr7\Uri implements the Psr7 Interface Psr\Http\Message\UriUriInterface, you can create your own Uri class and pass it to a Guzzle request.

use Psr\Http\Message\UriInterface;

// I didn't test it, it's just to demonstrate how a workaround could look like
MyUrl implements UriInterface
{
    private $parts;

    public function __construct($uri)
    {
        $this->parts = parse_url($uri);
    }

    public function getPath()
    {
        return $this->parts['path'];
    }

    public function getQuery()
    {
        return $this->parts['query'];
    }

    // you have to implement the other functions
}

use MyUrl;
$client->request('GET', new MyUrl('projects'));
DecolipAkira commented 2 years ago

I had the same problem, through this code:

public function getEntries($accessToken, $type) {
    $request = $this->guzzle->get('/entries', [
        'query' => [
            'filters' => 'type::in(' . $type . ')'
        ],
        'headers' => [
            'Content-Type'  => 'application/json',
            'Authorization' => 'Oauth ' . $accessToken
        ]
    ]);

    return $request->getBody();
}

My return was:

https://api.moip.com.br/entries?0=filters%3Dtype%3A%3Ain%28COMMISSION%29

Note: This was not my real problem, I passed the incorrect url, the correct one would be '/v2/entries' 😂😂

Fortunately I found a solution to this problem!

Solution:

use GuzzleHttp\Query;

public function getEntries($accessToken, $type) {
    $request = $this->guzzle->get('/entries', [
        'query' => Query::fromString('filters=type::in(' . $type . ')', false),
        'headers' => [
            'Content-Type'  => 'application/json',
            'Authorization' => 'Oauth ' . $accessToken
        ]
    ]);

    return $request->getBody();
}

The real solution lies in the method:

Query::fromString($query, $urlEncoding = true)

I'm glad I could help them!

Regards, Decolip Akira.

jamesmacwhite commented 9 months ago

I have found Guzzle 7 to be most problematic with the likes of Microsoft APIs when using OData, which have some exotic URL query parameters e.g. filters $filter=something eq 'value'. The space and single quote being encoded will break it, as it is not handled on the server end in that way. It goes beyond just query parameters, it's the whole URI value.

There is also information around disabling encoding but it's for older Guzzle versions, which don't apply to Guzzle 7. I think the only real solution is providing a Uri class that controls what happens, otherwise you'll just have issues, if you need specific control.