Skip to content
This repository has been archived by the owner on Dec 18, 2018. It is now read-only.

UnexpectUnexpected token G in JSON at position ed token G in JSON at position #1107

Closed
larserikfinholt opened this issue Nov 12, 2017 · 27 comments

Comments

@larserikfinholt
Copy link

It seems like the OPTIONS request to the hub returns "GET, HEAD" instead of an object. I think this issue is related, #1033

I've tried both IIS Express, and kestrel on win 10. There's an other user at SO with a similar issue: https://stackoverflow.com/questions/46825533/getting-error-while-trying-to-use-signalr-in-angular4-netcore-2-0-application

I'm using a plain mvc web app based on the chat sample in this sln https://github.com/aspnet/SignalR/tree/dev/samples/ChatSample

@moozzyk
Copy link
Contributor

moozzyk commented Nov 12, 2017

@larserikfinholt - how do I repro this? I am running the ChatSample quite often and have not seen this. There must be something missing in both reports which makes it hard to figure out what the problem is. Can you run your app with Kestrel only and turn on logging at the Trace level on the server and paste the logs? Do you see any errors/warnings in the logs?

@larserikfinholt
Copy link
Author

Sorry, I see no trace of the request hitting the server. Maybe there's something with the request thats beeing sent. It looks like this:

OPTIONS /multiplayer HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Origin: http://localhost:8080
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.89 Safari/537.36
Accept: */*
Referer: http://localhost:8080/
Accept-Encoding: gzip, deflate, br
Accept-Language: nb-NO,nb;q=0.9,no;q=0.8,nn;q=0.7,en-US;q=0.6,en;q=0.5,la;q=0.4,sv;q=0.3
Cookie: ai_user=g4TSp|2017-09-03T20:02:29.887Z

In addition I have the following:

   services.AddSignalR();

...

 app.UseSignalR(routes =>
            {
                routes.MapHub<MultiplayerHub>("multiplayer");
            });
...
    public class MultiplayerHub : Hub
    {
        public Task Send(string message)
        {
            return Clients.All.InvokeAsync("Send", message);
        }
    }
...
 <PropertyGroup>
    <TargetFramework>netcoreapp2.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <Folder Include="wwwroot\" />
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="MediatR" Version="3.0.1" />
    <PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="3.0.0" />
    <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" />
    <PackageReference Include="Microsoft.AspNetCore.Http" Version="2.0.0" />
    <PackageReference Include="Microsoft.AspNetCore.SignalR" Version="1.0.0-alpha2-final" />
    <PackageReference Include="Microsoft.Azure.DocumentDB.Core" Version="1.6.0" />
    <PackageReference Include="Swashbuckle.AspNetCore" Version="1.0.0" />
    <PackageReference Include="WindowsAzure.Storage" Version="8.5.0" />
  </ItemGroup>

  <ItemGroup>
    <DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.0" />
  </ItemGroup>



@cortexive
Copy link

cortexive commented Nov 12, 2017

@moozzyk I'm dealing with the same problem, and here's what the response to payload negotiation request in HttpConnection.ts looks like, in my case:

HTTP/1.1 200 OK
X-Powered-By: Express
Access-Control-Allow-Origin: *
Allow: GET,HEAD
Content-Type: text/html; charset=utf-8
Content-Length: 8
Date: Sun, 12 Nov 2017 12:05:54 GMT
Connection: keep-alive

Is it possible that the OPTIONS request to the hub is not being intercepted by the SignalR middleware?

@moozzyk
Copy link
Contributor

moozzyk commented Nov 12, 2017

@gateway7 - Doesn't the header X-Powered-By: Express indicate that the request was handled by expressjs?

@moozzyk
Copy link
Contributor

moozzyk commented Nov 12, 2017

@larserikfinholt - how does the response look like? Did you run Kestrel without anything (IIS/nginx) in front of it? Can you check if you did not get a cached response (e.g. from the browser's cache)?

@cortexive
Copy link

cortexive commented Nov 12, 2017

@moozzyk - client talks to directly to the service (no reverse proxies involved), which is hosted by Kestrel on Windows 10. I've no idea how expressjs got into the picture.

@moozzyk
Copy link
Contributor

moozzyk commented Nov 12, 2017

@gateway7 - can you try to figure out who is writing this header, whether the request actually hits the server at all, or if the response is coming from the browser's cache (look at the network tab in the developer tools)? btw. what browser do you use? I wonder if we need to add nonce to the request similarly to what we do for the long polling transport (#848).

@moozzyk
Copy link
Contributor

moozzyk commented Nov 12, 2017

@gateway7 @larserikfinholt - can you check if things start working if you add some random querystring to your url (e.g. ?test=112358)?

@cortexive
Copy link

cortexive commented Nov 13, 2017

@moozzyk

  • The scenario has been tested on the latest beta of Chrome x64 and the latest release versions of Edge and Firefox. All produce the same results.
  • Adding URL query didn't change anything.
  • The response indeed comes from the server (no cache involved). The one I posted earlier was taken from the network tab. Here's the full story:

image

@analogrelay
Copy link
Contributor

Have you ever run an Express-based app at the same URL (including port)? I think Chrome may aggressively cache CORS pre-flight data (i.e. Access-Control headers) and may be intercepting the OPTIONS request and returning a cached response even when the cache is disabled.

That would indicate that we should avoid using OPTIONS entirely for the negotiation request (cc @davidfowl @BrennanConroy )

@cortexive
Copy link

@anurse
The problem is not in Chrome or its caching policy, at least in my case. I get the same results in other browsers and even with .NET HttpClient running in LINQPad query. So it must be coming from a package running in the NG web server context. Taking into account the endless number of ExpressJS-dependant packages (20K+, according to npmjs.com), the only reasonable solution seems to be the one you've just suggested in #1111.

@davidfowl
Copy link
Member

Closing this out

@larserikfinholt
Copy link
Author

@moozzyk @davidfowl I'm really embarrassed to say this but I actualy tried to connect to the webserver that serves my SPA, not to the webapi. I could easily have spotted this looking at the OPTIONS request to /multiplayer, instead of http://localhost:5005/multiplayer.

Fixed by starting the connection with

this.connection = new HubConnection('http://localhost:5005/multiplayer');
instead of: this.connection = new HubConnection('/multiplayer');

Again, sorry for raising such a dumb issue.

@analogrelay
Copy link
Contributor

@larserikfinholt 😆 No worries, we've all done things like that. Glad to hear you got it working properly in the end!

@cuiliang
Copy link

cuiliang commented Jan 4, 2018

Made same mistake.
I am using angular client in another port served by ng serve
use new HubConnection('/hub'); will make the browser connect web server from angular-cli, which will not respond correctly.

It's better add some information to the document, or some comment to the sample code.

@andreisrob
Copy link

I am having the same problem as @gateway7. Any solution while still using Version="1.0.0-alpha2-final"?

@analogrelay
Copy link
Contributor

I am having the same problem as @gateway7

Can you confirm your configuration? What ASP.NET Core server are you using (Kestrel/IIS/etc.)? Can you look at the response you are getting the error from? It's likely an HTML page which may provide more information about the reason for the error.

@andreisrob
Copy link

I am using Kestrel, and the Response is sending back "GET, HEAD". I am running my Angular SPA on a separate server, but my connection string for HubConnection specifies the correct port (5000), so it's not the issue @cuiliang was dealing with.
Is there a way to configure the IHttpConnectionOptions to use a POST method instead of OPTIONS?

@analogrelay
Copy link
Contributor

analogrelay commented Mar 22, 2018

use a POST method instead of OPTIONS?

We did that in the preview 1 build. We don't patch or update old preview builds once the new one is released. You'll have to update to ASP.NET Core 2.1 Preview 1 to get the fix.

@andreisrob
Copy link

@anurse Yeah, I figured. Now I just have to convince my team to upgrade...

@andreisrob
Copy link

@anurse Before I make my case, do you have any idea why the OPTIONS negotiate request doesn't work? Is there any solution?

@analogrelay
Copy link
Contributor

do you have any idea why the OPTIONS negotiate request doesn't work? Is there any solution?

OPTIONS is primarily used by the CORS feature and a number of browsers/servers/proxies have strange behaviors with it. There is no solution that I'm aware of, so we simply switched to a POST in Preview 1.

Now I just have to convince my team to upgrade...

Do remember that our preview releases come with no guarantee of support. You should keep as current as possible during preview releases, because as soon as RTM is out, that'll be the only supported version. Also, we could really use the feedback. We recognize that upgrading between released versions can be difficult, but for preview releases, we strongly recommend you keep up-to-date, otherwise we won't be able to solve any problems you do encounter in time for RTM.

@andreisrob
Copy link

@anurse You have been very gracious with your time; perhaps you can help. I upgraded, and now the response from the negotiate request is indeed some HTML. It says Cannot POST /message/negotiate. Note that I get the same result whether I manually add /negotiate to the url (both in the angular HubConnection method and in my Startup.cs configure method), or just use /message.

@analogrelay
Copy link
Contributor

analogrelay commented Mar 22, 2018

I upgraded, and now the response from the negotiate request is indeed some HTML. It says Cannot POST /message/negotiate.

This seems very strange, there's nothing in ASP.NET Core that would produce this error as far as I'm aware. Are you sure you're connecting directly to your ASP.NET Core application and not to an intermediate proxy (such as Angular tools, etc.)? If you're using a relative URL, it might not be working properly, I suggest checking the Network tab of your browser dev tools and verifying that it's actually connecting to the SignalR endpoint.

If it is connecting to the right endpoint, you should check if you have any middleware above the UseSignalR call in your Startup.Configure method that could be intercepting the request.

@andreisrob
Copy link

I have tried very hard to figure out what's going wrong, but I got nothing.
Allow me to give you some info, and perhaps you can help.
My ASP.NET Core version is 2.1.300-preview1-008174
My npm @aspnet/signalr version is 1.0.0-preview1-update1
I am using the Angular Project Template with ASP.NET Core (https://docs.microsoft.com/en-us/aspnet/core/spa/angular?tabs=netcore-cli)
Although angular is getting served from a different server and port, I have configuration on Startup.cs that manages this, and the "origin" in all my requests is the ASP.NET Core server and port (localhost:5000), so there is no CORS issue.
I am using an absolute path for the connection url.
The string I use in app.UseSignalR() is "message", but the request adds /negotiate to the url
I do have some ASP.NET Core middleware, but they only manipulate the request under specific circumstances, none of which apply when the HubConnection request comes through. I put a breakpoint in my middleware, and the request is hitting the ASP.NET Core application.
I also have MVC routing configuration ("{controller=Home}/{action=Index}/{id?}"), but the app.UseSignalR() code precedes the app.UseMvc() code in my Configure method. Is it possible that MVC is looking for the controller named message and returns 404 when it doesn't find it?

@andreisrob
Copy link

I GOT IT!
I did not update my launch.json file, particularly this line:
"program": "${workspaceFolder}/src/WebApp/bin/Debug/netcoreapp2.0/"
So I was actually running the old version of ASP.NET Core, and that's why SignalR was not working.
When I built the packages, my csproj was indeed restoring with 2.1, so I mistakenly assumed that I was running the current version. Ouch.
Thanks for your time.

@analogrelay
Copy link
Contributor

No problem! Glad you got it sorted out!

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

No branches or pull requests

7 participants