WSO2 API Manager is not responding to a request that returns zip file (application/octet-stream) - api

Using WSO2 API Manager 1.3.1. Trying to use the API Manager to proxy to a REST service. I have set up the service in API Mgr and can successfully post and get responses, typically json, though some are text.
However, when I try to GET a resource that returns binary content (a zip "file", content-type:application/octet-stream), the API Manager does not seem to respond and I can see an error in the console window (i'm running wso2server.bat in console):
[2013-07-03 11:52:05,048] WARN - SourceHandler Connection time out
while writing the response: 173.21.1.22:1268->173.21.1.22:8280
I have an HTTPModule on my internal service and it seems to be responding with the appropriate content (I can see the GET and response data logged). I can also call to the internal service directly and get a response, so that end of things seems OK. But going through the API Manager seems to fail.
I found information on enabling other content-types:
WSO2 API Manager - Publishing API with non-XML response
http://wso2.com/library/articles/binary-relay-efficient-way-pass-both-xml-non-xml-content-through-apache-synapse
Using that information I tried to enable the application/octet-stream for messageFormatter and messageBuilder using the binary relay and it did not help (or seem to make a difference). I have even disabled all other content-types and use the binary relay for all content-types and it does not help.
Currently, I'm running with just the following in both axis2.xml and axis2_client.xml (in their appropriate sections):
<messageBuilder contentType=".*" class="org.wso2.carbon.relay.BinaryRelayBuilder"/
<messageFormatter contentType=".*" class="org.wso2.carbon.relay.ExpandingMessageFormatter"/>
I still get my json and text responses, but WSO2 times out getting the zip content. I saw the JIRA referenced in axis2.xml about enabling the ".*" relay, but as the other requests seem to work, I'm not sure it's an issue for me. I did try adding
'format="rest"' to the API definition, but it seemed to break all operations even the ones that worked prior so I've pulled it back out.
Any ideas on what is happening or how to dig in and debug this will help. Thanks!

After working with this for much too long, it turns out that my WSO2 configuration was correct, using the Message Relay and BinaryRelayBuilder, etc. While my REST service could reply immediately, I was setting a HTTP header that I assume WSO2 does not like, because when i removed it WSO2 would reply at an expected rate (instantly).
I was setting the header:
Transfer-Encoding: binary
When I removed that header from my service reply, then WSO2 operated as expected. I don't know if that's a "bug" in WSO2 or if I was implementing incorrectly, but I do have what seems like a "workaround" by omitting that header from my service response.

Related

Atlassian Connect - Set entity properties in Jira/Cloud

I develop an AC/SpringBoot Jira plugin which needs to store properties in the host application. Atlassian provides Hosted Data Storage which I like to use.
I ran a test via Firefox RESTClient to play around with this feature.
When issuing a GET request to this URL:
https://kuespert-dev.atlassian.net/rest/atlassian-connect/1/addons/<MY-PLUGIN-KEY>
while being logged in to my Jira/Cloud instance on another tab everything is fine: I get back information about my plugin, including the key.
However, when issuing a PUT request to set a variable (like described in the documentation mentioned above) using this URL:
https://kuespert-dev.atlassian.net/rest/atlassian-connect/1/addons/<MY-PLUGIN-KEY>/properties/testProperty
and this request body:
{"string":"string-value","number":5}
as well as the required header:
Content-Type: application/json
I get back this response:
{
"status-code": 404,
"message": "Add-on with key does not exist."
}
This is a bit irritating, since the first REST call did find my plugin while the second to the sub-resource did not.
A similar question was already asked on the 'Atlassian Community' site, but no solution was found until today.
Maybe it's just a wrong error message or something similar. Does anybody here have experience with the 'Hosted Data Storage' feature and can help?
Thanks,
Matthias

Possible proxy issue with WSO2 API Manager

Whenever I try to add the following endpoint, "http://ws.cdyne.com/phoneverify/phoneverify.asmx", during the Managed API setup process and press the Test button I get an error on the server. ERROR - APIProviderHostObject Error occurred while connecting to backend : "stackOverflow preventing me from showing this link", reason: Connect to ws.cdyne.com:80 timed out
When I try this exact same process on a machine outside of our proxy it works fine. I have gone into the axis2.xml file and added proxy information and even went as far as installing cntlm and setting the proxy to localhost - same error.
I can browse to the above link just fine on this machine.
My environment is Windows 10.
I assume you talk about clicking the Test button when providing Backend Endpoint in API publisher.
The way that Test button works at the moment (as far as I understand) is that it invokes HTTP HEAD method on the endpoint provided (because according to RFC 2616, "This method is often used for testing hypertext links for validity, accessibility, and recent modification.")
Then it checks response. If response is valid or 405 (method not allowed), then the URL is marked as Valid.
Thus sometimes, if backend is not properly following RFC, you might get otherwise working URLs declared as Invalid during the test because of that improper HEAD response evaluation. Obviously, this is just a check for your convenience and you can ignore the check if you know the endpoint works for the methods and resources you need it to work.
So my advice would be to try ignoring the Test and just finishing setting up and publishing the API.
P.S. I am checking it on WSO2 API Cloud but behavior is identical to downloadable API Manager.

How do I get Basic Authentication, GlassFish, REST, and a single page application to all work together with my own login form?

I'm using Glassfish 4 as a server with an AngularJS app as a client. Glassfish is exposing a REST API via JAX-RS (Jersey). I'm using Basic Authentication over an HTTPS connection. I have my own login form and am setting the Authorization header in my REST requests via JavaScript. My issue is that if I use normal web.xml based permissions (<auth-constraint> inside <security-constraint>), the responses come back with 401 with a WWW-Authenticate header (if the credentials are bad). This forces the browser to do the Basic Authentication dialog instead of my own and it appears there is no viable cross browser work around available on the browser side to stop it. So I need to somehow suppress the 401/WWW-Authenticate response.
I stopped using the web.xml based permissions, because it seems it is the Servlet level that is doing the 401 stuff. I was able to get Jersey authentication working with a filter and turning on the "RolesAllowedDynamicFeature" feature (in a matter similar to Glassfish #RolesAllowed with custom SecurityContext). That seems to work great and returns 403 for bad credentials (and thus no browser dialog). However, when I call my EJB's, they do not see the custom security context and the user I have set, so I get permission exceptions. If it matters: the EJB's are in a jar, the Jersey stuff is in a war, and both of them and bundled together in an ear. From what I can gather the only way to have the EJB's properly process credentials is to use the web.xml stuff.
I seemed to have painted myself into a corner and do not see how to make this work. Perhaps I can back out and return to using web.xml based permissions and somehow filter the servlet responses to not return 401/WWW-Authenticate? If so I could not find out how to do that. Or is there some way I can set EJB's security context? Or something else entirely? I wouldn't think using AngularJS with GlassFish and a REST API and Basic Authentication would be very unique, how does anyone do this?
Since posting this question I have found info on implementing a Servlet filter and using that to try to change the 401 response to a different status code. However, the filter never gains control if you have <auth-constraint> in your web.xml and the request is not authorized, so that did not help me. I still could not prevent the 401 responses.
But now I think I finally found the answer. I removed the <auth-constraint> tag from web.xml. I changed the Servlet filter to now extract the AUTHENTICATION_HEADER on its own and decode it (via javax.xml.bind.DatatypeConverter). Next I call HttpServletRequest.login (on the request object) with the decoded username and password. I catch the ServletException if the username/password combination is bad and use HttpServletResponse.sendError to send SC_FORBIDDEN. If I have a good login I call doFilter to continue on with processing of the request, and call HttpServletRequest.logout when it returns.
If I do this in combination with RolesAllowedDynamicFeature and annotations on the Jersey routines everything seems to work including calls to EJB's with their own security annotations.
Side note: before settling on HttpServletRequest.login I had tried to use HttpServletRequest.authenticate followed by checking the returned boolean, but when you gain control in that case the response has already been committed to be 401 and you cannot change it. I even tried passing a HttpServletResponseWrapper to authenticate to stop the commit from happening, but authenticate seems to get the response object through some other means, it seems to ignore the one you pass it (I even tried passed null and it didn't even notice).

Logging information appearing in Response

I am calling json api built using Symfony2 using LAMP stack.
URL for api is like
http://ab.ab.com/new/358342/17/12.948468/77.718571
Response I get back correctly:
{"Result":{"statusCode":1,"statusMsg":"Created Successfully"}}
However http headers contain the information I am logging in server. Example is
-wf-1-1-1-3:185|[{"Type":"INFO","File":"","Line":"","Label":"app"},"Data From Publisher Device Id:358342045834581 Route Id: 17 Lat:12.948468 Lng77.718571 Timestamp:2014-09-18 13:23:20 Data:tstsst|S-1"]|
Above logging info is coming back in Http header of response.
How should I disable the server logging info coming back.
Finally I figured it out.
I was using firephp handler and firephp adds the logging information back in response through http headers.
firephp is useful tool for debugging json apis, however should be disabled in production to avoid revealing sensitive information.
I switched to fingers_crossed handler.

WCF - JSONP Content-Length Issue

Scenario:
Web Service needed to calculate values and send results back as json. These calls are to be made cross-domain so I'm using jsonp. The problem I'm having occurs both on the same domain and cross-domain.
Problem:
I'm having an issue getting back json data from a WCF Service. While on my local machine it works fine, but when on the server the response from the service is cut short (if I run it through Visual Studio on the server though, it's fine).
The content length seems to be set as the length of my response before wrapping it in the jquery callback function (example data below).
Local: jQuery151017220264650085249_1309423933796({"d":"[\"Flat\",\"Terrace\",\"Semi\",\"Detached\",\"Bungalow\"]"});
Local: jQuery151017220264650085249_1309423933797({"d":"[\"New build\",\"2000 to 2010\",\"1990 to 2000\",\"1970 to 1990\",\"1950 to 1970\",\"Pre 1950\"]"});
Live: jQuery1510246237260361726_1309424024004({"d":"[\"Flat\",\"Terrace
Live: jQuery1510246237260361726_1309424024005({"d":"[\"New build\",\"2000 to 2010\",\"1990 to 2000\",\"1970 to
To wrap the json response with the callback function I had to use a httpmodule I found on the net.
The server uses IIS 7.5, locally i'm just using Visual Studio. (Some kind of IIS configuration?)
Right, hopefully I've provided enough information, if not let me know.
So if anyone has any idea how I could fix this issue it would be greatly appreciated.
Thanks
You don't need to use an HTTP Module to wrap the response in JSONP - this feature is available in WCF 4.0. You can set the property CrossDomainScriptAccessEnabled in WebHttpBinding, and if the request comes from a different domain (and it has a ?callback=FunctionName) parameter, the response will be wrapped in FunctionName(...).