We are getting thousands of websocket_handshake_failed on our GCP load balancer.
Our Environment is: App Engine Flex environment with auto-scale + Postgress cloud SQL
we have a chat SaaS application so we use sockets.
on the logging, I see +1000 websocket_handshake_failed each hour,
below is the sample of the log of a single error:
{
insertId: "1yr7yf8g129xnqm"
jsonPayload: {2}
httpRequest: {
requestMethod: "GET"
requestUrl: "https://platform.businesschat.io/socket/websocket?auth_token=SFMyNTY.g2gDdAAAAAFkAAd1c2VyX2lkYR5uBgBpppTkeAFiAAFRgA.KRJF8oZWOOtsOS0aqNUzf8OJgip-znonz31WSPGwUlQ&vsn=2.0.0"
requestSize: "2382"
status: 403
responseSize: "231"
userAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36"
remoteIp: "188.54.82.167"
serverIp: "10.156.0.30"
}
resource: {
type: "http_load_balancer"
labels: {
target_proxy_name: ""
url_map_name: ""
project_id: "businesschat-platform"
forwarding_rule_name: ""
backend_service_name: "aef-default-20210418t185059-bs"
zone: "global"
}
}
timestamp: "2021-04-19T10:05:16.050343Z"
severity: "WARNING"
logName: "projects/businesschat-platform/logs/requests"
trace: "projects/businesschat-platform/traces/2205a954ba0c5d518574a6b00316fa92"
receiveTimestamp: "2021-04-19T10:05:17.924136122Z"
spanId: "692567857ac6b22b"
}
on the front end, Am getting a sample connection: close error, not sure if that is related:
Related
I'm building a web-app and have chosen Spring for my backend and React for my frontend. I'm using Spring Security to provide authentication and authorisation:
#Configuration
#EnableWebSecurity
public class SecurityConfiguration {
#Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeHttpRequests((authz) -> authz
.antMatchers("/").permitAll()
.antMatchers("/register/**").permitAll()
.antMatchers("/aUrl/**").hasRole(aRole)
.antMatchers("/anotherUrl/**").hasRole(anotherRole)
.anyRequest().authenticated()
)
.formLogin((formLogin) ->
formLogin.permitAll().defaultSuccessUrl("/login/success")
)
.logout((logout) ->
logout.deleteCookies("remove")
.invalidateHttpSession(false)
.logoutSuccessUrl("/login")
);
return http.build();
}
#Bean
public PasswordEncoder passwordEncoder() {
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
}
and I was trying to submit the POST request through the following component:
class LoginForm extends React.Component{
constructor() {
super();
this.state = {
username: "",
password: ""
}
}
handleSubmit = (e) => {
const formData = new FormData();
formData.append("username", this.state.username);
formData.append("password", this.state.password);
fetch('/login', {
method: 'POST',
body: formData
})
e.preventDefault();
}
handleFieldChange = (event) => {
this.setState({[event.target.id]: event.target.value});
}
render(){
return (
<form onSubmit = {this.handleSubmit}>
<Input type="text" placeholder="username" id="username" label="Username:" value={this.state.username} onChange={this.handleFieldChange}/>
<Input type="text" placeholder="password" id="password" label="Password:" value={this.state.password} onChange={this.handleFieldChange}/>
<SubmitButton text="Log in"/>
</form>
);
}
}
I am basically trying to mimic the POST request sent by the browser in the following scenario:
<form method="post" action="/login">
<label htmlFor="username" >Username</label>
<input type="text" id="username" name="username" placeholder="Username" required="" autoFocus="" />
<label htmlFor="password">Password</label>
<input type="password" id="password" name="password" placeholder="Password" required="" />
<button type="submit">Log in</button>
</form>
The problem is that the latter works, the former does not. Specifically, I get a CORS policy error message that does not show up in the latter case, despite both pages being on the same port (3000), which is separate from the one that hosts the backend (8080) (N.B: I have declared a proxy as per React's indications). I am guessing that the request is somehow built differently, but I cannot imagine there wouldn't be a way to integrate a programmatic POST with Spring Security: am I simply not supposed to use form-based authentication?
Thank you in advance!
EDIT:
Here is my Spring log:
2022-10-21 10:03:57.303 INFO 15260 --- [ main] edu.devs.SomeApplication : Starting SomeApplication using Java 17.0.2 on *** with PID 15260
2022-10-21 10:03:57.306 INFO 15260 --- [ main] edu.devs.SomeApplication : No active profile set, falling back to 1 default profile: "default"
2022-10-21 10:03:58.117 INFO 15260 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data Neo4j repositories in DEFAULT mode.
2022-10-21 10:03:58.218 INFO 15260 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 85 ms. Found 4 Neo4j repository interfaces.
2022-10-21 10:03:59.397 INFO 15260 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2022-10-21 10:03:59.409 INFO 15260 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2022-10-21 10:03:59.410 INFO 15260 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.65]
2022-10-21 10:03:59.537 INFO 15260 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2022-10-21 10:03:59.538 INFO 15260 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 2106 ms
2022-10-21 10:04:00.106 INFO 15260 --- [ main] org.neo4j.driver.internal.DriverFactory : Routing driver instance 1107789101 created for server address ***:7687
2022-10-21 10:04:00.803 INFO 15260 --- [ main] o.s.s.web.DefaultSecurityFilterChain : Will secure any request with [org.springframework.security.web.session.DisableEncodeUrlFilter#c9b5a99, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter#70be89ec, org.springframework.security.web.context.SecurityContextPersistenceFilter#3e43f049, org.springframework.security.web.header.HeaderWriterFilter#2017f6e6, org.springframework.security.web.authentication.logout.LogoutFilter#d25e878, org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter#5384ce66, org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter#336f49a1, org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter#2aee0704, org.springframework.security.web.savedrequest.RequestCacheAwareFilter#755a7218, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter#58a7dc4, org.springframework.security.web.authentication.AnonymousAuthenticationFilter#19a5b637, org.springframework.security.web.session.SessionManagementFilter#79ca7bea, org.springframework.security.web.access.ExceptionTranslationFilter#5627cb29, org.springframework.security.web.access.intercept.AuthorizationFilter#125f16b2]
2022-10-21 10:04:01.409 INFO 15260 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2022-10-21 10:04:01.433 INFO 15260 --- [ main] edu.devs.SomeApplication : Started SomeApplication in 4.607 seconds (JVM running for 5.145)
2022-10-21 10:04:03.901 WARN 15260 --- [ main] o.s.d.n.c.m.DefaultNeo4jIsNewStrategy : Instances of class edu.devs.domain.Student with an assigned id will always be treated as new without version property!
2022-10-21 10:04:04.059 WARN 15260 --- [ main] o.s.d.n.c.m.DefaultNeo4jIsNewStrategy : Instances of class edu.devs.security.UserAuthority with an assigned id will always be treated as new without version property!
2022-10-21 10:04:04.441 WARN 15260 --- [ main] o.s.d.n.c.m.DefaultNeo4jIsNewStrategy : Instances of class edu.devs.domain.Admin with an assigned id will always be treated as new without version property!
2022-10-21 10:04:05.052 WARN 15260 --- [ main] o.s.d.n.c.m.DefaultNeo4jIsNewStrategy : Instances of class edu.devs.domain.School with an assigned id will always be treated as new without version property!
2022-10-21 10:04:05.264 WARN 15260 --- [ main] o.s.d.n.c.m.DefaultNeo4jIsNewStrategy : Instances of class edu.devs.domain.Classroom with an assigned id will always be treated as new without version property!
2022-10-21 10:04:29.586 INFO 15260 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2022-10-21 10:04:29.587 INFO 15260 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2022-10-21 10:04:29.588 INFO 15260 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 1 ms
and here is my browser console log:
Access to fetch at 'http://localhost:8080/login/success' (redirected from 'http://localhost:3000/login') from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
LoginForm.js:26 GET http://localhost:8080/login/success net::ERR_FAILED 302
all of which does not show up if I just use a declarative POST.
For good measure, I'm also including the request headers of both.
Here are those of the programmatically-sent request:
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: it-IT,it;q=0.9,en-US;q=0.8,en;q=0.7
Connection: keep-alive
Content-Length: 256
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryZva4mpEReAgtMlLA
Host: localhost:3000
Origin: http://localhost:3000
Referer: http://localhost:3000/login
sec-ch-ua: "Google Chrome";v="105", "Not)A;Brand";v="8", "Chromium";v="105"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36
and here are those of the one handled by the browser (the one that works no problem):
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate, br
Accept-Language: it-IT,it;q=0.9
Cache-Control: max-age=0
Connection: keep-alive
Content-Length: 43
Content-Type: application/x-www-form-urlencoded
Host: localhost:3000
Origin: http://localhost:3000
Referer: http://localhost:3000/login
sec-ch-ua: "Google Chrome";v="105", "Not)A;Brand";v="8", "Chromium";v="105"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36
Obviously I can see that the issue with the former request is that the server redirects the browser to a resource located on a different port, thus triggering a CORS policy error. What I do not get is why this does not happen with the latter request, although I'm guessing it's got something to do with the request headers(?).
When I send a task to a task queue it keeps failing and shows a http 404 (not found) error in the logs.
The project has been whitelisted for cloud tasks alpha on flexible.
I can send HTTP post requests to /endpointpath & /tasks/worker locally without any errors.
The endpoint works fine and adds the task to the task queue.
13:37:41.300 POST 200 0 B 422 ms curl/7.54.0 /endpointspath?key=keyremoved 0.0.0.0 - "POST endpointspath?key=keyremoved" 200 undefined "-" "curl/7.54.0"
The app is running as the default service.
app.go main func:
func main() {
r := mux.NewRouter()
r.HandleFunc("/", handler)
r.HandleFunc("/_ah/health", healthCheckHandler)
// Task handlers
r.Path("/tasks/worker").Methods("POST", "GET", "PUT").HandlerFunc(workerTaskHandler)
// Endpoints
r.Path("/endpointpath").Methods("POST").HandlerFunc(searchHandler)
http.Handle("/", r)
port := 8080
if portStr := os.Getenv("PORT"); portStr != "" {
port, _ = strconv.Atoi(portStr)
}
log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", port), nil))
}
abbreviated app.yaml:
runtime: go
env: flex
handlers:
- url: /tasks/.*
script: _go_app
- url: /.*
script: _go_app
Logs HTTP 404 response when queue dispatches request to worker:
10.0.0.1 - "POST /tasks/worker" 404 200 "-" "AppEngine-Google; (+http://code.google.com/appengine)"
Expand all | Collapse all {
httpRequest: {
latency: "0s"
referer: "-"
remoteIp: "10.0.0.1"
requestMethod: "POST"
requestUrl: "/tasks/worker"
responseSize: "200"
status: 404
userAgent: "AppEngine-Google; (+http://code.google.com/appengine)"
}
insertId: "......."
jsonPayload: {
appLatencySeconds: "-"
latencySeconds: "0.000"
time: null
trace: "......."
}
labels: {
appengine.googleapis.com/instance_name: "......"
appengine.googleapis.com/trace_id: "......."
compute.googleapis.com/resource_id: "......."
compute.googleapis.com/resource_name: "......"
compute.googleapis.com/zone: "us-central1-b"
}
logName: "projects/projectname/logs/appengine.googleapis.com%2Fnginx.request"
receiveTimestamp: "2017-12-09T10:56:14.794726383Z"
resource: {
labels: {
module_id: "default"
project_id: "projectname"
version_id: "....."
}
type: "gae_app"
}
timestamp: "2017-12-09T10:56:10.301Z"
}
The closest I can get GAE to find the tasks/worker url is by setting login:admin in app.yaml (even tho flex doesn't use this for authentication). This returns a 403 unauthorised error.
handlers:
- url: /tasks/.*
script: _go_app
login: admin
Here is the 403 response in the logs
{
httpRequest: {
latency: "0s"
referer: "-"
remoteIp: "10.0.0.1"
requestMethod: "POST"
requestUrl: "/tasks/worker"
responseSize: "162"
status: 403
userAgent: "AppEngine-Google; (+http://code.google.com/appengine)"
}
insertId: "....."
jsonPayload: {
appLatencySeconds: "-"
latencySeconds: "0.000"
time: null
trace: "....."
}
labels: {
appengine.googleapis.com/instance_name: "...."
appengine.googleapis.com/trace_id: "...."
compute.googleapis.com/resource_id: "...."
compute.googleapis.com/resource_name: "....."
compute.googleapis.com/zone: "us-central1-b"
}
logName: "projects/projectname/logs/appengine.googleapis.com%2Fnginx.request"
receiveTimestamp: "2017-12-09T13:35:59.986118082Z"
resource: {
labels: {
module_id: "default"
project_id: "projectname"
version_id: "....."
}
type: "gae_app"
}
timestamp: "2017-12-09T13:35:54.764Z"
}
Not sure if it's related but projectname.appspot.com/_ah/health returns this error:
{
"code": 5,
"message": "Method does not exist.",
"details": [
{
"#type": "type.googleapis.com/google.rpc.DebugInfo",
"stackEntries": [],
"detail": "service_control"
}
]
}
It turns out endpoints can't run on the same service as task handlers. Task handler url requests are blocked by the ESP proxy if they run on the same service in the flexible environment, and the service has the endpoints service enabled.
Run task handlers on a separate service and do not set "endpoints_api_service:" in the task handler service app.yaml file.
Doing so will prevent the queue from being able to dispatch to workers in the flexible environment.
This isn't mentioned in the app engine documentation which is kinda bizarre.
The "/_ah/health" issue was caused by this path not being set in the open api file. If this path isn't set the url isn't recognised by the proxy.
Docker supported the --log-driver=gcplogs option to log a Google Compute Engine instance to the Stackdriver Logging service (aka Google Cloud Logging). However, all log entries in the Logs Viewer page at https://console.cloud.google.com/logs have no severity level - the entire log line gets placed in a data field like this:
{
metadata: {
projectId: "my-project"
serviceName: "custom.googleapis.com"
labels: {
custom.googleapis.com/secondary_key: "secondary_key"
custom.googleapis.com/primary_key: "primary_key"
}
timestamp: "2016-05-10T00:07:28.700617425Z"
projectNumber: "12345"
}
insertId: "2016-05-09|17:07:28.706161-07|1.2.3.4|1234"
log: "gcplogs-docker-driver"
structPayload: {
container: {
imageName: "us.gcr.io/my-image/name"
created: "2016-05-09T15:09:15.15158629Z"
name: "/my-container"
id: "7b6f9fa1d7517e6a3004b8fa7e52asdfddd8e63d02e43afb3942681a56f4e"
imageId: "sha256:20605d3fdc700asdfa8b08a4aed1f745a0b5d9a8f08ae0db2f90af0bd093"
}
data: "2016-05-10 00:07:28,700 DEBUG [my-file:191][uWSGIWorker1Core0] Some log message here"
instance: {
zone: "us-east1-b"
name: "broker-1"
id: "12345"
}
}
}
I know that stdout and stderr of a Container get logged by Docker, but how can I configure things (Docker, Compute Engine, Stackdriver Logging) to parse my messages to have a log level?
I am using the below AngularJS client code to perform a HTTP post request with JSON formatted payload to the jersey rest service
patientMgmtModule.controller('NewPatientCtrl',
function NewPatientCtrl($scope, $http)
{
$scope.addPatient = function (){
var patientJSON = angular.toJson($scope.Patient);
console.log("Patient (JSON) is ============> " + patientJSON);
$http({
method: 'POST',
data: $scope.Patient,
url:'/ManagePatient/AddPatient',
headers: {'Content-Type':'application/x-www-form-urlencoded;application/json;'}
});
};
}
);
I have the following maven dependencies for Jersey:
<dependency>
<groupId>org.glassfish.jersey.archetypes</groupId>
<artifactId>jersey-quickstart-webapp</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
<version>2.0</version>
</dependency>
On the Server Side, I have
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import com.hms.app.ui.beans.Patient;
#Path("/ManagePatient")
public class PatientController {
#POST
#Path("/AddPatient")
#Consumes({MediaType.APPLICATION_JSON})
public String addPatient(Patient patient) {
System.out.println("Sarat's servlet called" );
//patient.toConsole();
System.out.println("Done Calling Patient To Console");
return "Done Calling Patient To Console";
}
}
When I submit the form on the client side, I see the below error in the chrome console -
POST http://localhost:8080/HMS_Web/services/ManagePatient/AddPatient 500 (Internal Server Error) angular.min.js:99
and on the server end, I see (high level detail 1):
SEVERE: Servlet.service() for servlet [Jersey REST Service] in context with path [/HMS_Web] threw exception
org.glassfish.jersey.message.internal.HeaderValueException: Unable to parse "Content-Type" header value: "application/x-www-form-urlencoded;application/json;"
and the last stack trace has this:
Caused by: java.text.ParseException: Expected separator '=' instead of '/'
Detailed stack trace: (
Aug 01, 2013 9:28:18 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [Jersey REST Service] in context with path [/HMS_Web] threw exception
org.glassfish.jersey.message.internal.HeaderValueException: Unable to parse "Content-Type" header value: "application/x-www-form-urlencoded;application/json;"
at org.glassfish.jersey.message.internal.InboundMessageContext.exception(InboundMessageContext.java:318)
at org.glassfish.jersey.message.internal.InboundMessageContext.singleHeader(InboundMessageContext.java:313)
at org.glassfish.jersey.message.internal.InboundMessageContext.getMediaType(InboundMessageContext.java:427)
at org.glassfish.jersey.servlet.WebComponent.filterFormParameters(WebComponent.java:482)
at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:303)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:372)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:335)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:218)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:929)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1002)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:585)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
Caused by: javax.ws.rs.ProcessingException: java.lang.IllegalArgumentException: Error parsing media type 'application/x-www-form-urlencoded;application/json;'
at org.glassfish.jersey.message.internal.InboundMessageContext$5.apply(InboundMessageContext.java:433)
at org.glassfish.jersey.message.internal.InboundMessageContext$5.apply(InboundMessageContext.java:427)
at org.glassfish.jersey.message.internal.InboundMessageContext.singleHeader(InboundMessageContext.java:311)
... 22 more
Caused by: java.lang.IllegalArgumentException: Error parsing media type 'application/x-www-form-urlencoded;application/json;'
at org.glassfish.jersey.message.internal.MediaTypeProvider.fromString(MediaTypeProvider.java:89)
at org.glassfish.jersey.message.internal.MediaTypeProvider.fromString(MediaTypeProvider.java:59)
at javax.ws.rs.core.MediaType.valueOf(MediaType.java:179)
at org.glassfish.jersey.message.internal.InboundMessageContext$5.apply(InboundMessageContext.java:431)
... 24 more
Caused by: java.text.ParseException: Expected separator '=' instead of '/'
at org.glassfish.jersey.message.internal.HttpHeaderReader.nextSeparator(HttpHeaderReader.java:115)
at org.glassfish.jersey.message.internal.HttpHeaderReader.readParameters(HttpHeaderReader.java:261)
at org.glassfish.jersey.message.internal.HttpHeaderReader.readParameters(HttpHeaderReader.java:242)
at org.glassfish.jersey.message.internal.MediaTypeProvider.valueOf(MediaTypeProvider.java:107)
at org.glassfish.jersey.message.internal.MediaTypeProvider.fromString(MediaTypeProvider.java:87)
... 27 more
Aug 01, 2013 9:29:00 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [Jersey REST Service] in context with path [/HMS_Web] threw exception
org.glassfish.jersey.message.internal.HeaderValueException: Unable to parse "Content-Type" header value: "application/x-www-form-urlencoded;application/json;"
at org.glassfish.jersey.message.internal.InboundMessageContext.exception(InboundMessageContext.java:318)
at org.glassfish.jersey.message.internal.InboundMessageContext.singleHeader(InboundMessageContext.java:313)
at org.glassfish.jersey.message.internal.InboundMessageContext.getMediaType(InboundMessageContext.java:427)
at org.glassfish.jersey.servlet.WebComponent.filterFormParameters(WebComponent.java:482)
at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:303)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:372)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:335)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:218)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:929)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1002)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:585)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
Caused by: javax.ws.rs.ProcessingException: java.lang.IllegalArgumentException: Error parsing media type 'application/x-www-form-urlencoded;application/json;'
at org.glassfish.jersey.message.internal.InboundMessageContext$5.apply(InboundMessageContext.java:433)
at org.glassfish.jersey.message.internal.InboundMessageContext$5.apply(InboundMessageContext.java:427)
at org.glassfish.jersey.message.internal.InboundMessageContext.singleHeader(InboundMessageContext.java:311)
... 22 more
Caused by: java.lang.IllegalArgumentException: Error parsing media type 'application/x-www-form-urlencoded;application/json;'
at org.glassfish.jersey.message.internal.MediaTypeProvider.fromString(MediaTypeProvider.java:89)
at org.glassfish.jersey.message.internal.MediaTypeProvider.fromString(MediaTypeProvider.java:59)
at javax.ws.rs.core.MediaType.valueOf(MediaType.java:179)
at org.glassfish.jersey.message.internal.InboundMessageContext$5.apply(InboundMessageContext.java:431)
... 24 more
Caused by: java.text.ParseException: Expected separator '=' instead of '/'
at org.glassfish.jersey.message.internal.HttpHeaderReader.nextSeparator(HttpHeaderReader.java:115)
at org.glassfish.jersey.message.internal.HttpHeaderReader.readParameters(HttpHeaderReader.java:261)
at org.glassfish.jersey.message.internal.HttpHeaderReader.readParameters(HttpHeaderReader.java:242)
at org.glassfish.jersey.message.internal.MediaTypeProvider.valueOf(MediaTypeProvider.java:107)
at org.glassfish.jersey.message.internal.MediaTypeProvider.fromString(MediaTypeProvider.java:87)
... 27 more
After implementing LoggingFilter - I see that the server is responding with HTTP 415.
Aug 04, 2013 10:28:25 AM org.glassfish.jersey.filter.LoggingFilter log
INFO: 2 * LoggingFilter - Request received on thread tomcat-http--11
2 > POST http://localhost:8080/HMS_Web/services/ManagePatient/AddPatient
2 > host: localhost:8080
2 > connection: keep-alive
2 > content-length: 341
2 > accept: application/json, text/plain, */*
2 > origin: http://localhost:8080
2 > x-requested-with: XMLHttpRequest
2 > user-agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.72 Safari/537.36
2 > content-type: application/json
2 > dnt: 1
2 > referer: http://localhost:8080/HMS_Web/views/Landing.html
2 > accept-encoding: gzip,deflate,sdch
2 > accept-language: en-US,en;q=0.8
Aug 04, 2013 10:28:25 AM org.glassfish.jersey.filter.LoggingFilter log
INFO: 2 * LoggingFilter - Response received on thread tomcat-http--11
2 < 415
Your Content-Type header is invalid (see spec 14.17 Content-Type). Based on you JAX-RS resource you should use application/json as Content-Type (without application/x-www-form-urlencoded):
$http({
method: 'POST',
data: $scope.Patient,
url:'/ManagePatient/AddPatient',
headers: {'Content-Type':'application/json'}
});
EDIT 1:
If you want to see requests that are coming to your server you can register LoggingFilter and it will show you some useful information. You can turn it on in:
web.xml (add it to the JAX-RS servlet definition):
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>org.glassfish.jersey.filter.LoggingFilter</param-value>
</init-param>
Application extension:
public class MyApplication extends Application {
#Override
public Set<Class<?>> getClasses() {
return new HashSet<Class<?>>() {{
// Add your resources.
add(HelloWorldResource.class);
// Add LoggingFilter.
add(LoggingFilter.class);
}};
}
}
ResourceConfig instance (demonstrating also outputting the entity here):
public class MyApplication extends ResourceConfig {
public MyApplication() {
// Resources - add your package name here to enable package scanning.
packages(...);
// Enable LoggingFilter & output entity.
registerInstances(new LoggingFilter(Logger.getLogger(MyApplication.class.getName()), true));
}
}
EDIT 2:
Jersey 2.x does not support application/json media type out of the box - you need to add one of the JSON modules to your classpath (see JSON section in users guide), for example:
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
<version>2.0</version>
</dependency>
The following code generates a CGI method instead of WSGI as indicated in the log below. Is this the normal execution for a WSGI app on the dev server? If not what needs to change to get the application to execute as WSGI?
main.py
import webapp2
import wsgiref.handlers
import logging
from google.appengine.api import users
class HomeHandler(webapp2.RequestHandler):
def get(self):
self.response.out.write("Hi World")
app = webapp2.WSGIApplication([
(r'/', HomeHandler),
], debug=True)
app.run()
app.yaml
application: WSGITEST
version: 1
runtime: python27
api_version: 1
threadsafe: yes
libraries:
- name: webapp2
version: latest
handlers:
- url: /.*
script: main.app
Log
DEBUG 2012-05-09 21:31:14,921 dev_appserver.py:656] Matched "/" to CGI dispatcher with path main.app
DEBUG 2012-05-09 21:31:14,926 dev_appserver_import_hook.py:1246] Enabling webapp2: None
DEBUG 2012-05-09 21:31:14,928 dev_appserver.py:1624] Executing CGI with env:
{'REQUEST_ID_HASH': '77DE68DA', 'SERVER_SOFTWARE': 'Development/1.0', 'SCRIPT_NAME': '', 'REQUEST_METHOD': 'GET', 'PATH_INFO': '/', 'SERVER_PROTOCOL': 'HTTP/1.0', 'QUERY_STRING': '', 'CONTENT_LENGTH': '', 'USER_ID': '', 'APPENGINE_RUNTIME': 'python27', 'TZ': 'UTC', 'SERVER_NAME': 'localhost', 'REMOTE_ADDR': '127.0.0.1', 'SDK_VERSION': '1.6.5', 'PATH_TRANSLATED': '/home/bear/dev/appengine/code/ae-baseapp/401/main3.app', 'SERVER_PORT': '8080', '_AH_THREADSAFE': '1', 'CURRENT_VERSION_ID': '1.1', 'USER_ORGANIZATION': '', 'HTTP_USER_AGENT': 'Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:12.0) Gecko/20100101 Firefox/12.0', 'HTTP_HOST': 'localhost:8080', 'HTTP_CONNECTION': 'keep-alive', 'USER_EMAIL': '', 'HTTP_ACCEPT': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'APPLICATION_ID': 'dev~WSGITEST', 'GATEWAY_INTERFACE': 'CGI/1.1', 'HTTP_ACCEPT_LANGUAGE': 'en-us,en;q=0.5', 'HTTP_DNT': '1', 'CONTENT_TYPE': 'application/x-www-form-urlencoded', '_AH_ENCODED_SCRIPT_NAME': '/', 'AUTH_DOMAIN': 'gmail.com'}
INFO 2012-05-09 21:31:14,933 dev_appserver.py:2891] "GET / HTTP/1.1" 200 -
this log is a hardcoded string:
/usr/local/google_appengine/google/appengine/tools/dev_appserver.py:
1622 sys.modules['__builtin__'] = __builtin__
1623
1624: logging.debug('Executing CGI with env:\n%s', repr(env))
First, you should remove this line of code because it's incorrect:
app.run()
As written in my comment and well pointed out by aschmid00, could be an old debug statement.