Apache HTTPAsyncClient closes connection before response - https

I am sending a GET request to an API using the Apache AsyncHTTPClient version 4.1.4 (latest). I can't seem to get a response from the server.
This is my request log.
Jun 04, 2020 3:40:01 PM org.apache.http.impl.nio.client.MainClientExec generateRequest
FINE: [exchange: 2] Connection route established
Jun 04, 2020 3:40:01 PM org.apache.http.impl.nio.client.MainClientExec generateRequest
FINE: [exchange: 2] Attempt 1 to execute request
Jun 04, 2020 3:40:01 PM org.apache.http.impl.nio.client.MainClientExec generateRequest
FINE: [exchange: 2] Proxy auth state: UNCHALLENGED
Jun 04, 2020 3:40:01 PM org.apache.http.headers onRequestSubmitted
FINE: http-outgoing-1 >> GET /v1/contact?id=24 HTTP/1.1
Jun 04, 2020 3:40:01 PM org.apache.http.headers onRequestSubmitted
FINE: http-outgoing-1 >> Authorization: Bearer <token_removed>
Jun 04, 2020 3:40:01 PM org.apache.http.headers onRequestSubmitted
FINE: http-outgoing-1 >> Host: api.trial.ezyvet.com
Jun 04, 2020 3:40:01 PM org.apache.http.headers onRequestSubmitted
FINE: http-outgoing-1 >> Connection: Keep-Alive
Jun 04, 2020 3:40:01 PM org.apache.http.headers onRequestSubmitted
FINE: http-outgoing-1 >> User-Agent: Apache-HttpAsyncClient/4.1.4 (Java/11.0.6)
Jun 04, 2020 3:40:01 PM org.apache.http.impl.nio.conn.ManagedNHttpClientConnectionImpl setEvent
FINE: http-outgoing-1 192.168.1.2:52932<->52.27.52.37:443[ACTIVE][rw:][ACTIVE][rw][NEED_UNWRAP][0][0][437]: Event set [w]
Jun 04, 2020 3:40:01 PM org.apache.http.impl.nio.client.MainClientExec requestCompleted
FINE: [exchange: 2] Request completed
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 14.622 s
When I send the same request using Postman, I get a successful response.
This is my code to handle the connection.
public void connect(HttpUriRequest request, FutureCallback<HttpResponse> callback) {
SSLContextBuilder sslContextBuilder = new SSLContextBuilder();
try {
sslContextBuilder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
try (CloseableHttpAsyncClient client = HttpAsyncClients.custom()
.setSSLContext(sslContextBuilder.build())
.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
.build()) {
client.start();
client.execute(request, callback).get();
}
} catch (Exception e) {
Logger.getGlobal().severe("Couldn't execute the request using the AsyncClient.");
}
}
My debugger won't get triggered in any of the callback's methods (completed, failed, cancelled). Apparently the connection gets terminated for some reason.
Can someone explain what is happening here?
Thanks

I managed to solve this issue by changing the code to include a CountDownLatch instead of using client.execute(request, callback).get().
I passed down the latch to where the HttpResponse is read by JSON deserializer and count it down after everything completes.
This answer helped a lot.
https://stackoverflow.com/a/49359725/6663366

Related

Issue logging into Azure B2C Angular application using #azure/msal-angular

I'm having an odd error logging my app into B2C using auth code flow with PKCE using the #azure/msal-angular library. I'm redirecting back to the B2C login, get redirected back to my app, my app successfully gets a token back from the token api but then a JS error is logged and prevents my app from continuing to load. Here is the console output:
[Thu, 27 Jan 2022 22:34:53 GMT] : #azure/msal-angular#2.1.0 : Info - Interceptor - 1 scopes found for endpoint
msal-config.module.ts:27 [Thu, 27 Jan 2022 22:34:54 GMT] : #azure/msal-angular#2.1.0 : Info - Interceptor - 1 scopes found for endpoint
msal-config.module.ts:27 [Thu, 27 Jan 2022 22:34:54 GMT] : #azure/msal-angular#2.1.0 : Info - Interceptor - 1 scopes found for endpoint
msal-config.module.ts:27 [Thu, 27 Jan 2022 22:34:54 GMT] : #azure/msal-angular#2.1.0 : Info - Interceptor - 1 scopes found for endpoint
core.js:40853 Angular is running in the development mode. Call enableProdMode() to enable the production mode.
msal-config.module.ts:27 [Thu, 27 Jan 2022 22:34:54 GMT] : #azure/msal-browser#2.21.0 : Info - Emitting event: msal:handleRedirectStart
core.js:40853 Angular is running in the development mode. Call enableProdMode() to enable the production mode.
msal-config.module.ts:27 [Thu, 27 Jan 2022 22:34:54 GMT] : #azure/msal-angular#2.1.0 : Error - Interceptor - acquireTokenSilent rejected with error. Invoking interaction to resolve.
msal-config.module.ts:27 [Thu, 27 Jan 2022 22:34:54 GMT] : #azure/msal-browser#2.21.0 : Info - Emitting event: msal:loginStart
msal-config.module.ts:27 [Thu, 27 Jan 2022 22:34:54 GMT] : #azure/msal-angular#2.1.0 : Error - Interceptor - acquireTokenSilent rejected with error. Invoking interaction to resolve.
msal-config.module.ts:27 [Thu, 27 Jan 2022 22:34:54 GMT] : #azure/msal-browser#2.21.0 : Info - Emitting event: msal:loginStart
msal-config.module.ts:27 [Thu, 27 Jan 2022 22:34:54 GMT] : #azure/msal-angular#2.1.0 : Error - Interceptor - acquireTokenSilent rejected with error. Invoking interaction to resolve.
msal-config.module.ts:27 [Thu, 27 Jan 2022 22:34:54 GMT] : #azure/msal-browser#2.21.0 : Info - Emitting event: msal:loginStart
msal-config.module.ts:27 [Thu, 27 Jan 2022 22:34:54 GMT] : #azure/msal-angular#2.1.0 : Error - Interceptor - acquireTokenSilent rejected with error. Invoking interaction to resolve.
msal-config.module.ts:27 [Thu, 27 Jan 2022 22:34:54 GMT] : #azure/msal-browser#2.21.0 : Info - Emitting event: msal:loginStart
4msal-config.module.ts:27 [Thu, 27 Jan 2022 22:34:54 GMT] : #azure/msal-browser#2.21.0 : Info - Emitting event: msal:loginFailure
4core.js:6241 ERROR Error: Uncaught (in promise): BrowserAuthError: interaction_in_progress: Interaction is currently in progress. Please ensure that this interaction has been completed before calling an interactive API. For more visit: aka.ms/msaljs/browser-errors.
BrowserAuthError: interaction_in_progress: Interaction is currently in progress. Please ensure that this interaction has been completed before calling an interactive API. For more visit: aka.ms/msaljs/browser-errors.
at BrowserAuthError.AuthError [as constructor] (AuthError.js:27:1)
at new BrowserAuthError (BrowserAuthError.js:169:1)
at Function.push.../../node_modules/#azure/msal-browser/dist/error/BrowserAuthError.js.BrowserAuthError.createInteractionInProgressError (BrowserAuthError.js:236:1)
at RedirectClient.<anonymous> (StandardInteractionClient.js:216:51)
at step (_tslib.js:75:1)
at Object.next (_tslib.js:56:45)
at _tslib.js:49:1
at new ZoneAwarePromise (zone-evergreen.js:960:1)
at __awaiter (_tslib.js:45:1)
at RedirectClient.push.../../node_modules/#azure/msal-browser/dist/interaction_client/StandardInteractionClient.js.StandardInteractionClient.preflightInteractiveRequest (StandardInteractionClient.js:207:25)
at resolvePromise (zone-evergreen.js:798:1)
at zone-evergreen.js:705:1
at zone-evergreen.js:721:1
at ZoneDelegate.invoke (zone-evergreen.js:364:1)
at Object.onInvoke (core.js:41667:1)
at ZoneDelegate.invoke (zone-evergreen.js:363:1)
at Zone.run (zone-evergreen.js:123:1)
at zone-evergreen.js:857:1
at ZoneDelegate.invokeTask (zone-evergreen.js:399:1)
at Object.onInvokeTask (core.js:41645:1)
defaultErrorLogger # core.js:6241
handleError # core.js:6294
next # core.js:42627
schedulerFn # core.js:37132
__tryOrUnsub # Subscriber.js:183
next # Subscriber.js:122
_next # Subscriber.js:72
next # Subscriber.js:49
next # Subject.js:39
emit # core.js:37092
(anonymous) # core.js:41707
invoke # zone-evergreen.js:364
run # zone-evergreen.js:123
runOutsideAngular # core.js:41501
onHandleError # core.js:41704
handleError # zone-evergreen.js:368
runGuarded # zone-evergreen.js:136
api.microtaskDrainDone # zone-evergreen.js:670
drainMicroTaskQueue # zone-evergreen.js:576
Promise.then (async)
scheduleMicroTask # zone-evergreen.js:552
scheduleTask # zone-evergreen.js:388
onScheduleTask # zone-evergreen.js:272
scheduleTask # zone-evergreen.js:378
scheduleTask # zone-evergreen.js:210
scheduleMicroTask # zone-evergreen.js:230
scheduleResolveOrReject # zone-evergreen.js:847
resolvePromise # zone-evergreen.js:785
(anonymous) # zone-evergreen.js:705
webpackJsonpCallback # bootstrap:25
(anonymous) # mcl-portal-order.js:1
capture_page_info.js:954 Gather controls: 2.934814453125 ms
msal-config.module.ts:27 [Thu, 27 Jan 2022 22:34:54 GMT] : [64b25cee-dd82-4679-8a9e-b4eb65289ff3] : #azure/msal-common#6.0.0 : Info - in acquireToken call
DevTools failed to load source map: Could not load content for chrome-extension://lkoeejijapdihgbegpljiehpnlkadljb/browser-polyfill.js.map: HTTP error: status code 404, net::ERR_UNKNOWN_URL_SCHEME
client:52 [WDS] Live Reloading enabled.
msal-config.module.ts:27 [Thu, 27 Jan 2022 22:34:54 GMT] : #azure/msal-browser#2.21.0 : Info - Emitting event: msal:loginSuccess
msal-config.module.ts:27 [Thu, 27 Jan 2022 22:34:54 GMT] : #azure/msal-browser#2.21.0 : Info - Emitting event: msal:handleRedirectEnd
If refresh my app after this happens the app loads fine and calls all my api endpoints appropriately using the token it got. So it's just the inital process of bootstraping my app, redirecting to the login, getting redirected back to my app, posting the token request then something fails inbetween the time the token is received but before the api requests are made?
Have I configured this wrong?
my MsalConfigModule that sets up the configuration of the MsalModule:
const isIE = window.navigator.userAgent.indexOf("MSIE ") > -1 || window.navigator.userAgent.indexOf("Trident/") > -1; // Remove this line to use Angular Universal
export function loggerCallback(logLevel: LogLevel, message: string) {
console.log(message);
}
export function MSALInstanceFactory(config: ConfigService): IPublicClientApplication {
const authConf = config.getSettings()['oauthConfig'][0] as any;
const authConfig = new PublicClientApplication({
auth: {
clientId: authConf['client_id'],
authority: authConf.authority,
knownAuthorities: [authConf.authority],
redirectUri: authConf['redirect_uri'],
postLogoutRedirectUri: authConf['redirect_uri'],
navigateToLoginRequestUrl: true
},
cache:{
cacheLocation: BrowserCacheLocation.SessionStorage,
storeAuthStateInCookie: isIE
},
system: {
loggerOptions: {
loggerCallback,
logLevel: LogLevel.Info,
piiLoggingEnabled: false
}
}
});
return authConfig;
}
export function MSALInterceptorConfigFactory(config: ConfigService): MsalInterceptorConfiguration {
const resourceMap = new Map<string, Array<string>>();
// iterate over the urlMappings config and create a protectedresourcemap
const configUrls = config.getSettings()['urlMappings'] as Array<any>;
const scope = config.getSettings()['oauthConfig'][0].scope as string;
configUrls.map(urlMap => resourceMap.set(`${urlMap.url}/*`, [scope]));
return {
interactionType: InteractionType.Redirect,
protectedResourceMap: resourceMap
};
}
export function MSALGuardConfigFactory(): MsalGuardConfiguration {
return {
interactionType: InteractionType.Redirect
};
}
#NgModule({
providers: [],
imports: [MsalModule]
})
export class MsalConfigModule {
static forRoot() {
return {
ngModule: MsalConfigModule,
providers: [
{
provide: MSAL_INSTANCE,
useFactory: MSALInstanceFactory,
deps: [ConfigService]
},
{
provide: MSAL_GUARD_CONFIG,
useFactory: MSALGuardConfigFactory,
deps: [ConfigService]
},
{
provide: MSAL_INTERCEPTOR_CONFIG,
useFactory: MSALInterceptorConfigFactory,
deps: [ConfigService]
},
MsalService,
MsalGuard,
MsalBroadcastService,
{
provide: HTTP_INTERCEPTORS,
useClass: MsalInterceptor,
multi: true
}
]
};
}
}
part of my main app module:
#NgModule({
declarations: [AppComponent],
imports: [
...
MsalConfigModule.forRoot()
],
providers: [
DatePipe,
SlicePipe
],
bootstrap: [AppComponent, MsalRedirectComponent],
})
export class AppModule {}
The solution to this was for me to add the
canActivate:[MsalGuard]
guard to all my routes. I think the underlying problem was that the interceptor was looking for a token to send in the api requests before we had a token to send. Adding the guard prevented the activation of the route until we are authenticated and then once the the route was activated my api requests would fire, the interceptors would have thier token to send along and everything just worked.
I guess the take way is that you do need to add the MsalGuard, it's not enough to provide the interceptors and configure the protected resource map.

Strip Resource from Request Path in AWS Lambda Proxy Integration

I have a lambda function and API gateway deployed through terraform. The API gateway has multiple resources under the top-level root resource / such as /first and /second. The resource for /first is set up with lambda-proxy integration (ANY and /first and ANY on /first/{proxy+}). The /second resource points to a different integration.
My lambda is an ASP.NET Core 3.1 with Lambda Custom Runtime generated initially with dotnet new serverless.AspNetCore30WebApi but later updated to 3.1 when support was added to AWS.
My issue is that when the lambda proxy integration transforms the request to be sent to the lambda function, it includes the full resource name (i.e. /first/Product instead of just /Product). Since my REST API in the lambda function only knows about Products and doesn't have a concept of what first is, I get 404 results for anything forwarded through the API gateway. I can't seem to find a place to strip the resource name from the path before it's forwarded on to the lambda function, because with the lambda proxy integration, it doesn't seem like you have a chance to do any request mapping templates or substitutions.
Thu Jun 03 12:24:52 UTC 2021 : HTTP Method: GET, Resource Path: /first/Product
Thu Jun 03 12:24:52 UTC 2021 : Method request path: {proxy=Product}
Thu Jun 03 12:24:52 UTC 2021 : Method request query string: {}
Thu Jun 03 12:24:52 UTC 2021 : Method request headers: {}
...
Thu Jun 03 12:24:52 UTC 2021 : Endpoint request body after transformations: <<relevant snippet parts formatted below>>
{
"resource": "/first/{proxy+}",
"path": "/first/Product",
"httpMethod": "GET",
"pathParameters": {
"proxy": "Product"
},
"requestContext": {
"resourcePath": "/first/{proxy+}",
"httpMethod": "GET",
"path": "/first/{proxy+}",
"protocol": "HTTP/1.1"
}
}

AWS Lambda: Can't access event['param'] via URL but it works on API GW Test

import json
def lambda_handler(event, context):
return {
"statusCode": 200,
"headers": {"Content-Type": "application/json"},
"body": json.dumps(event['param'])
}
I'm not sure what I'm doing wrong. I succesfully setup API Gateway, a Python Lambda Function, proper DNS via Route53 and a valid TLS cert...
I can access my Lambda via calling mydomain.com/lambda but I'm not getting any params to pass through, only this error. Been trying for 5 frustrating hours now.
When called via mydomain.com/lambda
errorMessage "'param'"
errorType "KeyError"
stackTrace
0 " File \"/var/task/lambda_function.py\", line 7, in lambda_handler\n \"body\": json.dumps(event['param'])\n"
When called via API Gateway's "Test" (all good here)
Execution log for request
Tue Nov 05 22:42:47 UTC 2019 : Starting execution for request:
Tue Nov 05 22:42:47 UTC 2019 : HTTP Method: GET, Resource Path: /
Tue Nov 05 22:42:47 UTC 2019 : Method request path: {}
Tue Nov 05 22:42:47 UTC 2019 : Method request query string: {}
Tue Nov 05 22:42:47 UTC 2019 : Method request headers: {}
Tue Nov 05 22:42:47 UTC 2019 : Method request body before transformations:
Tue Nov 05 22:42:47 UTC 2019 : Endpoint request URI:
Tue Nov 05 22:42:47 UTC 2019 : Endpoint request headers: {x-amzn-lambda-integration-tag=Authorization=...[TRUNCATED]
Tue Nov 05 22:42:47 UTC 2019 : Endpoint request body after transformations:
{
"param" : "foo"
}
Tue Nov 05 22:42:47 UTC 2019 : Sending request to
Tue Nov 05 22:42:47 UTC 2019 : Received response. Status: 200, Integration latency: 36 ms
Tue Nov 05 22:42:47 UTC 2019 : Endpoint response headers: [...]
Tue Nov 05 22:42:47 UTC 2019 : Successfully completed execution
Tue Nov 05 22:42:47 UTC 2019 : Method completed with status: 200
And finally success (via API Gateway's "Test")
{
"statusCode": 200,
"headers": {
"Content-Type": "application/json"
},
"body": "\"foo\""
}
How to get it working via URL? I try to actually get some header params from the client (browser) but step-by-step to learn. Seems I cannot even get anything to pass through from API Gateway to Lambda when called via URL, but why? What am I not getting here conceptually? :(
I set it all up correctly but didn't know that I had to re-deploy the API to make changes happen publicly.
That was the answer: Deploy the API again.

Grizzly HttpServer clean shutdown got WARNING: GRIZZLY0032

I was trying to clean shutdown grizzly server. I was calling the httpServer.shutdown()
However, while I was running "mvm clean test", I got warnings like
Aug 03, 2014 10:39:00 PM org.glassfish.grizzly.http.server.NetworkListener start
INFO: Started listener bound to [localhost:8081]
Aug 03, 2014 10:39:00 PM org.glassfish.grizzly.http.server.HttpServer start
INFO: [HttpServer] Started.
Aug 03, 2014 10:39:00 PM org.glassfish.grizzly.http.server.NetworkListener shutdownNow
INFO: Stopped listener bound to [localhost:8081]
Aug 03, 2014 10:39:00 PM org.glassfish.grizzly.nio.GracefulShutdownRunner run
WARNING: GRIZZLY0030: Shutting down transport TCPNIOTransport[428da4da] in 10,000 SECONDS.
Aug 03, 2014 10:39:00 PM org.glassfish.grizzly.nio.GracefulShutdownRunner run
WARNING: GRIZZLY0032: Primary shutdown thread interrupted. Forcing transport termination.
Here is my code to shutdown the host.
protected static void shutdownGrizzlyWebServer(HttpServer grizzlyWebServer) {
if (grizzlyWebServer != null && grizzlyWebServer.isStarted()) {
GrizzlyFuture<HttpServer> future = grizzlyWebServer.shutdown(10000, TimeUnit.MILLISECONDS);
while (!future.isDone()) {
try {
Thread.sleep(2000);
} catch (InterruptedException ignore){
System.out.println(ignore);
}
}
Does anyone have any idea what goes wrong here? Thank you very much.

Disconnecting Atmosphere sockets in Grails

I'm writing a Grails application which uses Atmosphere plugin. The connection works but every time I update the page in a browser I see that my web server adds a new Daemon thread which is never released afterwards.
After the thread count reaches 200 the web server freezes.
There seems to be no documentation explaining what is exactly the right way to handle the resources (disconnect) with the Atmosphere plugin?
My client code does this:
var connectedEndpoint = null;
$(function()
{
function callback(response)
{
if (response.transport != 'polling' && response.state != 'connected' && response.state != 'closed') {
if (response.status == 200) {
eval(response.responseBody);
}
}
}
$.atmosphere.subscribe('${resource(dir: '/atmosphere/channel')}', callback, $.atmosphere.request = {transport: 'streaming'});
connectedEndpoint = $.atmosphere.response;
});
$(window).unload( function ()
{
$.atmosphere.unsubscribe();
connectedEndpoint = null;
});
I use an atmosphere handler on the server side;
package demo
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse
import org.atmosphere.cpr.AtmosphereHandler
import org.atmosphere.cpr.AtmosphereResource;
import org.atmosphere.cpr.AtmosphereResourceEvent;
class DemoController implements AtmosphereHandler<HttpServletRequest, HttpServletResponse> {
#Override
public void destroy() {
println "destroy"
}
#Override
public void onRequest( AtmosphereResource<HttpServletRequest, HttpServletResponse> event) throws IOException
{
event.suspend()
}
#Override
public void onStateChange( AtmosphereResourceEvent<HttpServletRequest, HttpServletResponse> event) throws IOException
{
if (event.isSuspended())
{
event.resource.response.writer.with {
def message = event.message
write "set${message.paramName}(\"${message.id}\",\"${message.value}\");"
flush()
}
}
}
}
The destroy function of the handler is never called!
The next picture shows that I have 23 threads running. When I start my application there are about 6 of them and they are added every time I press F5! If I disable atmosphere new threads are not added so this problem is related to the Atmosphere. (I am using SpringSource Tools Suite on Windows7).
If the solution is not trivial I would appreciate detailed step-by step instructions or an example.
UPDATE: After deployment in Tomcat I have the following errors each 20 seconds:
Apr 02, 2012 2:35:15 PM org.apache.catalina.startup.HostConfig deployDescriptor
INFO: Deploying configuration descriptor host-manager.xml
Apr 02, 2012 2:35:16 PM org.apache.catalina.startup.HostConfig deployDescriptor
INFO: Deploying configuration descriptor manager.xml
Apr 02, 2012 2:35:16 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory docs
Apr 02, 2012 2:35:16 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory examples
Apr 02, 2012 2:35:17 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory ROOT
Apr 02, 2012 2:35:17 PM org.apache.coyote.http11.Http11AprProtocol start
INFO: Starting Coyote HTTP/1.1 on http-8080
Apr 02, 2012 2:35:17 PM org.apache.coyote.ajp.AjpAprProtocol start
INFO: Starting Coyote AJP/1.3 on ajp-8009
Apr 02, 2012 2:35:17 PM org.apache.catalina.startup.Catalina start
INFO: Server startup in 11401 ms
2012-04-02 14:41:17,122 [http-8080-39] ERROR cpr.AsynchronousProcessor - failed
to timeout resource AtmosphereResourceImpl{, hasCode-1035775543,
action=org.atmosphere.cpr.AtmosphereServlet$Action#f2718e,
broadcaster=org.atmosphere.cpr.DefaultBroadcaster,
cometSupport=org.atmosphere.container.TomcatCometSupport#107fff7,
serializer=null,
isInScope=true,
useWriter=true,
listeners=[]}
2012-04-02 14:42:15,034 [http-8080-69] ERROR cpr.AsynchronousProcessor - failed
to timeout resource AtmosphereResourceImpl{, hasCode-58082012,
action=org.atmosphere.cpr.AtmosphereServlet$Action#ae4dd4,
broadcaster=org.atmosphere.cpr.DefaultBroadcaster,
cometSupport=org.atmosphere.container.TomcatCometSupport#107fff7,
serializer=null,
isInScope=true,
useWriter=true,
listeners=[]}
2012-04-02 14:44:41,159 [http-8080-13] ERROR cpr.AsynchronousProcessor - failed
to timeout resource AtmosphereResourceImpl{, hasCode648226529,
action=org.atmosphere.cpr.AtmosphereServlet$Action#507e61,
broadcaster=org.atmosphere.cpr.DefaultBroadcaster,
cometSupport=org.atmosphere.container.TomcatCometSupport#107fff7,
serializer=null,
isInScope=true,
useWriter=true,
listeners=[]}
....
Which web server are you using? Sound like the web server isn't detecting when the browser close the connection. You can add, in web.xml, the following timeout detector
org.atmosphere.cpr.CometSupport.maxInactiveActivity=30000 //30 seconds
I believe your issue is in your unload event. "$(window).unload". I know at least in chrome, you can't do much in the unload or beforeunload events. therefore, your browser is probably never firing the unsubscribe().
if u look at Atmospheres jquery pubsub sample, u can see the unsubscribing before connecting,
function connect() {
unsubscribe();
...
you can code a loop to check broadcasters by pushing insignificant data to validate the broadcasters periodically if they arent getting cleaned up. i need to research atmosphere more and hope for a better solution. hopefully you can clean up threads when the new connection is created from a refresh and let old ones expire with the session when the user leaves.

Resources