Complex routing WSO2 API resourse uri template - url-rewriting

Short Version.
I am trying to create a API that will handle
/goals/risks
/goals/types
/goals/{goalID}
So far this is what I have but it isn't quite what I am looking for. as it gives me /goals/goal/{goalId}
<api xmlns="http://ws.apache.org/ns/synapse" name="GoalAPI" context="/goals">
<resource methods="GET" uri-template="/risks" faultSequence="ReturnError">...</resource>
<resource methods="GET" uri-template="/types" faultSequence="ReturnError">...</resource>
<resource methods="GET" uri-template="/goal/{goalId}" faultSequence="ReturnError">...</resource>
</api>
GoalID will always match /^\d+$/ so if I can route by that somehow it will work. eventually I will want to add /goals/{goalID}/item and /goals/{goalID}/items/{itemID} also but I believe that will be easy enough once I figure out the first step.
If there is no way to do this here, is there a way I can rewrite the url inside wso2 before it reaches the resource and I would be able to then replace /goals/(\d+.*) with /goals/goal/$1? I know I could route it though a proxy and rewrite it in apache or something but that seems to defeat WSO2's purpose to me.

So after looking into this more without success and getting no response on I just stared at the code can came up with...
<api xmlns="http://ws.apache.org/ns/synapse" name="GoalAPI" context="/goals">
<resource methods="GET" uri-template="/{goalID}" faultSequence="ReturnError">
<inSequence>
<switch source="get-property('uri.var.goalId')">
<case regex="risks">...</case>
<case regex="types">...</case>
<default>...Handle the ID here...</default>
</switch>
</inSequence>
...
</resource>
</api>

Related

ImageURL got expired after some particular time

I am having set of URLs which needs to converted to base64 in order to push image to Salesforce File object in WSO2 EI 6.3.0. while converting imageUrl to base64 i'm getting "expires" value too old message.
here is my code. `
<call>
<endpoint>
<http method="get" uri-template="{uri.var.url}"/>
</endpoint>
</call>
<log level="full" seperator="====Base64Content===="/>
<enrich description="EnrichFileContent">
<source clone="true" type="body"/>
<target property="image_val" type="property"/>
</enrich>
<log level="custom">
<property name="===image_val===" expression="get-property('image_val')"/>
</log>
`
I am pretty much sure that there is no issue in my code. because by using that same code , i can retrieved base64 from that same url which previously works. after some time it gets expired.
FYI,
ImageURL: https://carsales.pxcrush.net/car/dealer/y67p1dpz5f7zc3swhxi93ur9e.jpg?pxc_expires=20191203040935&pxc_clear=1&pxc_size=2500,2500&pxc_method=limit&pxc_signature=db8a850b8401d95b37fa3658a2fcbb5e
Getting base64 from ImageURL
It seems that the error message is getting printed even if you directly access the URL via browser. Isn't it?
I changed the "pxc_expires" query param to a newer one "pxc_expires=20191226040935". Now I got a different error.
Bad signature
Then I removed the "pxc_signature=db8a850b8401d95b37fa3658a2fcbb5e" altogether, then I was able to retrieve the image.
Are you sure you are accessing the image from the correct URL? I think, using the correct image URL would solve the problem.

Getting No 'Access-Control-Allow-Origin' when sending large JSON via AJAX

I'm working on a web page that calls a REST webservice via ajax to get and insert data.
The problem is that we need to send a base64 image in a JSON. You know, the base64 image is the imaged converted to that large text: base64/fjhd7879djkdadys7d9adsdkjasjdshk...
When we try with a 1 KB image, it works.
But with a bigger file(55kb), it doesn't.
So I assume it has something to do with the maxRequest, but the error says that is No 'Access-Control-Allow-Origin'. But we havent fount any way to configure it. Please help.
By default browsers block json requests from other domains other than the page unless the json request has the Access-Control-Allow-Origin header, so you'll need to add that header to your json requests on that service or use the same domain for both.
More info here: https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS
You can try setting the maxJsonLength to it's maximum value in the web.config file.
<system.web.extensions>
<scripting>
<webServices>
<jsonSerialization maxJsonLength="2147483647"/>
</webServices>
</scripting>
</system.web.extensions>
I know this is an old post, but for anyone who still might be having this problem, I solved it by adding two settings to Web.config as described here: https://west-wind.com/webconnection/docs/_4lp0zgm9d.htm
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="2147483647"></requestLimits>
</requestFiltering>
</security>
<!--snip-->
</system.webServer>
and
<system.web>
<httpRuntime maxRequestLength="2147483647" />
<!--snip-->
</system.web>

HttpWebRequest "keep-alive" header gets dropped

I am in NTLM hell here, hope you can help indentify what I am missing.
I am ultimately trying to deliver SSRS reports to a frame in a browser, and only the images within the reports are giving me much grief. They don't appear unless the user has Firefox and enters their credentials 2 times, first for the report, then a second time for the images in the report.
I am using HttpWebRequest to obtain the SSRS reports.
I am sending the webserver (IIS 7.5) a credential cache with "NTLM" and valid credentials to try and obtain an images from SSRS after I receive the HTML stream so that I can store them locally and refer to those, which would alleviate the users from having to re-enter credentials again and again.
I see in Fiddler that Type 1, 2 and 3 challenges are properly met during the NTLM hand shaking, however, the final response is 500 internal service error. The response text also indicates rsStreamNotFound, however, I find next to no info on what that means and I think it's misleading as to what the real problem may be.
When I use Firefox, Firefox prompts me for my network credentials for the report and then again for the images, and it gets through bringing the images back. My HttpWebRequest fails with 500 Internal Server Error, and rsStreamNotFound.
The only difference I can see in the request headers between Firefox requests and my requests is that the "keep-alive" property gets dropped from my programmatic request, and the Firefox requests have it in there.
Why do my "keep-alive" get dropped?
At this point, that is the only difference between my request and the request from Firefox, so I would like to eliminate that difference before jumping to any other conclusion.
I tried variations of:
req.KeepAlive = true;
req.PreAuthenticate = true;
and this gem:
var sp = req.ServicePoint;
var prop = sp.GetType().GetProperty( "HttpBehaviour", BindingFlags.Instance | BindingFlags.NonPublic );
prop.SetValue( sp, (byte)0, null );
Here is the CredentialCache:
CredentialCache credentialCache = new CredentialCache();
credentialCache.Add( new Uri( path ), "NTLM", NetCredentials );
... and "keep-alive" is not present in the request for my HttpWebRequest, and Firefox has it - why does mine get dropped?
Update:
I tried:
using (WebClient client = new WebClient()) {
client.DownloadFile(url, filePath);
}
...and I got 401 Unauthorized, so I tried with credentials and get 500 Internal Server Error
It is not clear from your question where you are running the code. Is it running on the desktop as an executable? Or is it running inside firefox as some sort of activex control or something similar?
Anyway, I suggest using .net tracelog facility to get a log of your transaction, and look at the logfile.
<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
<system.diagnostics>
<trace autoflush="true" />
<sources>
<source name="System.Net">
<listeners>
<add name="System.Net"/>
</listeners>
</source>
<source name="System.Net.Sockets">
<listeners>
<add name="System.Net"/>
</listeners>
</source>
<source name="System.Net.Cache">
<listeners>
<add name="System.Net"/>
</listeners>
</source>
</sources>
<sharedListeners>
<add
name="System.Net"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="System.Net.trace.log"
/>
</sharedListeners>
<switches>
<add name="System.Net" value="Verbose" />
<add name="System.Net.Sockets" value="Verbose" />
<add name="System.Net.Cache" value="Verbose" />
</switches>
</system.diagnostics>
</configuration>
If your app name is app.exe, create a file called app.exe.config in the same directory as the exe, and put the above contents into it. Then run the app, and a logfile should be created.
This link should have more information on getting logfiles, in case you have a problem.
creating a system.net trace log
You can put the logfile on pastebin after deleting personal information like hostnames, ipaddresses etc.
Also, give us a snippet of code that reproduces the problem. Then it will be easier to help.

How to redirect a http POST with urlrewritefilter

I have a question about the urlrewritefilter and until now I could not find anything about it in the net.
I want to redirect a http POST in Tomcat7. Here is an example...
The call is a HTTP POST to an ULR like
http://localhost:8080/oldApplication/Example?a=123&b=2
This call also contains some content either as xml or json. The filter is configured well as it works and the urlrewrite.xml contains:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 4.0//EN"
"http://www.tuckey.org/res/dtds/urlrewrite4.0.dtd">
<urlrewrite use-query-string="true">
<rule>
<condition type="method">POST</condition>
<from>^(.*)$</from>
<to type="redirect">/newApplication$1</to>
</rule>
</urlrewrite>
In the access log I can see that a call to
http://localhost:8080/oldApplication/Example?a=123&b=2
gets redirected to
http://localhost:8080/newApplication/Example?a=123&b=2
Fine until now. The problem is that the rewrite changes the method, so that the new url gets called with a HTTP GET instead of a HTTP POST. I tried to add a condition on the method but got still a HTTP GET after the rewrite.
Does anybody know how to configure the rewritefilter to avoid this?
You are using the type attribute redirect on type="redirect"
This attribute is equivalent to HttpServletResponse.sendRedirect() that actually does a new request to the destination using the GET method, so all parameters are lost along with the HTTP method.
The default value for this attribute if not informed is forward that is equivalent to HttpServletRequest.getRequestDispatcher(url).forward()
Forwarding will keep all request parameters and also the HTTP method.
So, in order to obtain the desired result you have to omit your type attribute or set it to forward.
<to>/newApplication$1</to>
or
<to type="forward">/newApplication$1</to>

Can you use node.js with IIS?

This may be an extremely simple quesiton, but can I use node.js in a windows server 2008 environment with IIS? Is there a "Microsoft" library or some other solution that works better?
Sure you can, check out the IISNode Project.
You can install Node.js on Windows, but it is its own server, so unless you're using IIS as a proxy to it, there's no need for IIS at all. Note, though, the following as quoted from Node.js's installation instructions:
Neither [Windows] builds are satisfactorily stable but it is possible to get something running.
You essentially have two routes for running a Node.js application via IIS.
IISNode
Reverse Proxy using Application Request Routing
If you are dedicating an entire application to Node.js and simply need the public facing endpoint to work through your existing IIS Application, I would suggest using ARR to route the entire site through. I'm doing this for a couple of projects, and it works fairly well.
To be honest, I haven't liked IISNode, as it seems like you are making alien endpoints in your node code vs. IIS. It works, and if you are targeting Azure in particular it may be your best option. It also may be the best option if you have to shoe horn it into an existing .Net application.
I have been using Node on Windows with Cygwin and had few problems. You can use IIS to serve on default port 80 and run your Node apps on different ports.
If you want to proxy then most are using Nginx.
You can build node.js on Windows, but it's not recommended to use it due to possible stability issues. If IIS is using thread based pools then you shouldn't even use it as a reverse proxy (on linux based systems nginx is usually used to do this) for node.js because pool may quickly become fully loaded. If you want something similar to node.js on windows then you should try to look at manos.
I wanted to make it as easy as possible.
Issues with iisnode
I installed iisnode and ran the samples with no problem but...
I tried to deploy it on IIS with iisnode, but I had to bundle my meteor app and then deploy it as a node app. The problem I ran into discouraged me. I could not get fibers to install at all. compilation process kept trowing errors, so I gave up.
Reverse Proxy IIS
What I did to solve this for me is use a reverse proxy on IIS.
see my post on meteor forum
My final web.config entry was:
I did the same, however, the way I had the reverse proxy on IIS to use
a sub folder on the domain threw me of.
I was not aware that by using ROOT_URL we could specify the a sub
path.
example, if i run the following command inside my meteor app folder:
set ROOT_URL=http://localhost:3100/n/todos && meteor
I will be able to access my app at http://localhost:3100/n/todos,
notice I omitted the trailing /. And if we try to surf to the
address http://localhost:3100/n or http://localhost:3100/ will
give us an error Unknown path.
So, when I first setup the reverse proxy, I was getting the Unknown
Path error every time.
Turns out that on my IIS config, I have to specify the
http://localhost:3100/n/todos as the url value on the action, please
notice the "n/todos" at the end.
So my rewrite rule ended up like this: [file #
c:/inetpub/wwroot/web.config]
```
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="TODOs meteor app. Route the requests" stopProcessing="true" enabled="true">
<match url="^n/todos/(.*)" />
<conditions>
<add input="{CACHE_URL}" pattern="^(https?)://" />
</conditions>
<action type="Rewrite" url="{C:1}://localhost:3100/n/todos/{R:1}" /> <!-- I was missing the /n/todos here -->
<serverVariables>
<set name="HTTP_ACCEPT_ENCODING" value="" />
</serverVariables>
</rule>
</rules>
<outboundRules>
<rule name="TODOs ReverseProxyOutboundRule1" preCondition="ResponseIsHtml1" enabled="false">
<match filterByTags="A, Area, Base, Form, Frame, Head, IFrame, Img, Input, Link, Script" pattern="^http(s)?://localhost:3100/(.*)" />
<action type="Rewrite" value="/n/todos/{R:2}" />
</rule>
<rule name="TODOs RewriteRelativePaths" preCondition="ResponseIsHtml1" enabled="false">
<match filterByTags="A, Area, Base, Form, Frame, Head, IFrame, Img, Input, Link, Script" pattern="^/(.*)" negate="false" />
<action type="Rewrite" value="/n/todos/{R:1}" />
</rule>
<rule name="ReverseProxyOutboundRule1" preCondition="ResponseIsHtml1">
<match filterByTags="A, Form, Img" pattern="^http(s)?://localhost:3100/(.*)" />
<action type="Rewrite" value="http{R:1}://localhost/{R:2}" />
</rule>
<preConditions>
<preCondition name="ResponseIsHtml1">
<add input="{RESPONSE_CONTENT_TYPE}" pattern="^text/html" />
</preCondition>
</preConditions>
</outboundRules>
</rewrite>
</system.webServer>
</configuration>
```
Thanks

Resources