dougdellolio / coinbasepro-csharp

The unofficial .NET/C# client library for the Coinbase Pro/GDAX API
MIT License
193 stars 90 forks source link

ProductService throwing "Request headers must contain only ASCII characters" #290

Open pridmorej opened 3 years ago

pridmorej commented 3 years ago

Hello, I'm encountering the following error when calling both GetProductTickerAsync and GetProductStatsAsync. Can you please help figure out what is going wrong. I'm just passing in a string product id. I took a look at the source code in this repo, but can't see why the methods would be failing as they are just calling SendServiceCall in the same way as many other places.

I am connected to Coinbase using the following method... Client = new CoinbasePro.CoinbaseProClient(authenticator, IsSandbox)

Here's the call stack... System.Net.Http.HttpRequestException: Request headers must contain only ASCII characters. at System.Net.Http.HttpConnection.WriteStringAsync(String s, Boolean async) at System.Net.Http.HttpConnection.WriteStringAsync(String s, Boolean async, Encoding encoding) at System.Net.Http.HttpConnection.WriteHeadersAsync(HttpHeaders headers, String cookiesFromContainer, Boolean async) at System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken) at System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken) at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken) at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken) at System.Net.Http.DiagnosticsHandler.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken) at System.Net.Http.HttpClient.SendAsyncCore(HttpRequestMessage request, HttpCompletionOption completionOption, Boolean async, Boolean emitTelemetryStartStop, CancellationToken cancellationToken) at CoinbasePro.Network.HttpClient.HttpClient.SendAsync(HttpRequestMessage httpRequestMessage, CancellationToken cancellationToken) at CoinbasePro.Network.HttpClient.HttpClient.SendAsync(HttpRequestMessage httpRequestMessage) at CoinbasePro.Services.AbstractService.SendHttpRequestMessageAsync(HttpMethod httpMethod, String uri, String content) at CoinbasePro.Services.AbstractService.SendServiceCall[T](HttpMethod httpMethod, String uri, String content) at CoinbasePro.Services.Products.ProductsService.GetProductStatsAsync(String productId)

dougdellolio commented 3 years ago

hi @pridmorej, I haven't seen this error before. are you only see this error on those 2 calls? few things to maybe try here.

  1. Try calling GetProductTickerAsync() without the authenticator since these calls don't require authentication and see if this works. If that's the case perhaps there's something wrong with the values you are passing into the authenticator object

    var coinbaseProClient = new CoinbaseProClient(true);
    var result = coinbaseProClient.ProductsService.GetProductTickerAsync("BTC-USD").Result;
  2. Check the headers before they are sent and make sure they are appearing properly. You can set a breakpoint on line 62 in HttpRequestMessageService and hover over the "requestMessage" to view the different headers.

If none of these steps highlight the problem you might have to provide some more code and versions you are using as it's hard to tell otherwise. Hope this helps.

pridmorej commented 3 years ago

Hi Doug, thanks for your speedy reply. I used a separate CoinbaseProClient which is not authenticated and it is working fine. I've only used an Authenticated one so far, so hadn't considered trying an Unauthenticated one. It was on my backlog to do anyway! :-)

pridmorej commented 3 years ago

Hi Doug, so I'm kicking myself for not testing this sooner, but I have discovered that Coinbase is only throwing this error for one of my API keys, in particular it is one where the passphrase contains one or more £ characters. I have two API Keys, one View and one View/Trade. The other key has a passphrase that contains one or more $ characters. I'm sure I was using the View/Trade Api Key and didn't have any issue with it, however, I moved the Api Keys from an appsetting.json file into a table in a mssqllocaldb database, and now it seems to be throwing this error. When I look at the System.Text.Encodings.UTF8.GetBytes, there is actually 13 bytes rather than 12. The £ is encoded using 2 bytes 194 and 163, where as the $ character is only encoded with 1 byte. I'm probably getting too deep at this point, so question - what is the CoinbaseProClient doing with headers? Is it encoding them as utf-8? Maybe you could see if you get the same issue using a passphrase with a £ character?

dougdellolio commented 3 years ago

hey @pridmorej, the client isn't doing anything special here when adding the passphrase to the headers. see code here: https://github.com/dougdellolio/coinbasepro-csharp/blob/3f31c86ae8b1c64b1637e55836058dc05655df59/CoinbasePro/Network/HttpRequest/HttpRequestMessageService.cs#L78

I am not too sure why this would be an issue but sounds like the best bet is to not add those characters into the passphrase if possible. When creating an API key, Coinbase provides the passphrase for you which seem to never include special characters by default (only A-Z, 0-9). let me know if you're still seeing issues with it