Hi guys!
I created a Github-Repository which will hold all files published/described on my blog.
This should help you guys downloading/using the stuff.
Have fun!
Beware... IT inside ;-)
Dienstag, 5. November 2013
PHP-Proxy for Carte
Hi again!
my first post was dealing with a JSP-based proxypage to enable "crosssite javascripting" access to the Carte-Service.
Now it´s time to serve the same approach for the PHP-folks out there.
Basically, all you need is:
<?
$url = $_GET["url"];
$url .= "?1=1";
foreach ( $_GET as $getKey => $getVar ) {
//print $getVar;
if ( $getKey != "url" ) {
$url .= "&".$getKey."=".str_replace(" ","+",urlencode($getVar));
}
}
// tested with such urls:
// http://localhost/test/proxy.php?url=http://localhost:8888/kettle/transStatus/&name=Row+generator+test&id=ee8d2d9d-da0a-404c-8488-ededf6b176df&xml=y
//echo $url;
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_HEADER, true);
curl_setopt($curl, CURLOPT_USERPWD, "cluster:cluster");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($curl);
$content = curl_getinfo($curl,CURLINFO_CONTENT_TYPE);
header("Content-type: ".$content);
// pretty ugly but I could not come up with a simpler approach to separate the HTTP-Headers from the Content
$response_arr = explode("\r\n",$response);
$startresponse = false;
$responsetext = "";
foreach ( $response_arr as $line ) {
if ( trim($line) == "" ) {
$startresponse = true;
}
if ( $startresponse ) {
$responsetext .= $line;
}
}
echo $responsetext;
?>
To download the file directly, head over to github: proxy.php
Please mind the linebreaks when downloading/installing the file.
Anyway, I hope this file will satisfy the PHP-guys and be of some use for you out there!
Thanks for reading, see you next time.
my first post was dealing with a JSP-based proxypage to enable "crosssite javascripting" access to the Carte-Service.
Now it´s time to serve the same approach for the PHP-folks out there.
Basically, all you need is:
- PHP (I used version 5.5.4, but any v5 should be good I think)
- curl-Extension activated in your PHP (please refer to php.net for details)
<?
$url = $_GET["url"];
$url .= "?1=1";
foreach ( $_GET as $getKey => $getVar ) {
//print $getVar;
if ( $getKey != "url" ) {
$url .= "&".$getKey."=".str_replace(" ","+",urlencode($getVar));
}
}
// tested with such urls:
// http://localhost/test/proxy.php?url=http://localhost:8888/kettle/transStatus/&name=Row+generator+test&id=ee8d2d9d-da0a-404c-8488-ededf6b176df&xml=y
//echo $url;
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_HEADER, true);
curl_setopt($curl, CURLOPT_USERPWD, "cluster:cluster");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($curl);
$content = curl_getinfo($curl,CURLINFO_CONTENT_TYPE);
header("Content-type: ".$content);
// pretty ugly but I could not come up with a simpler approach to separate the HTTP-Headers from the Content
$response_arr = explode("\r\n",$response);
$startresponse = false;
$responsetext = "";
foreach ( $response_arr as $line ) {
if ( trim($line) == "" ) {
$startresponse = true;
}
if ( $startresponse ) {
$responsetext .= $line;
}
}
echo $responsetext;
?>
To download the file directly, head over to github: proxy.php
Please mind the linebreaks when downloading/installing the file.
Anyway, I hope this file will satisfy the PHP-guys and be of some use for you out there!
Thanks for reading, see you next time.
Mittwoch, 9. Oktober 2013
Carte and Crosssite-Scripting? Come on!
Welcome to my very first blog-post!
I would like to start off with a short "Thank you" to all of the Pentaho OpenSource-community
out there. Being a very responsive and supportive community I experienced a warm and healthy
environment ever since starting using the Pentaho BI-Suite (PDI, BI-Server and many of the infamous plugins) about 6 years ago.
This being said I would like to dive straight ahead into the post...
Lately I came across an intersting situation which this blogpost will talk about:
Making PDI/Carte-"services" available for other websites.
In short, this post will assume you to have some basic knowledge about:
To start, I would like to describe my intial problem, then display the solution I came up with while
being on-site at the customer.
As almost always, there´s many ways to solve a given problem, so please don't be picky about me if you and your solution are fit better for your needs.
Ok, now let´s go!
Problem
My situation was, to have the Carte-Service running on a given computer with also having a JBoss AS server deployed on another (or maybe the same) machine.
So we end up with Carte listening on http://localhost:8888 (Basic-Authentication active) and the
JBoss listening on http://localhost:8080 and having a bunch of apps deployed on the JBoss.
From inside one of these apps my goal was to access some KTRs on Carte via Web (e.g.: http://localhost:8888/kettle/executeTrans/?trans=getMeSomeData.ktr)
and return the data from the KTR to the requesting jQuery/AJAX call, which basically is something like this:
$.ajax({
url : 'http://localhost:8888/kettle/executeTrans/?trans=getMeSomeData.ktr',
method : 'GET',
success: function(data) {
doSomethingWithTheData(data)
}
})
However, having the originating request coming from localhost:8080 and requesting data from localhost:8888 causes an obvious problem:
"Crosssite scripting"!
Thus, jQuery requires you to use "CORS/JSONP" which just did not work for me.
Solution
So I ended up thinking about another approachand "proxy'ing" came to my mind.
In the end, I did some research and since I did not want to setup proxy-rules inside my JBoss I was looking for a more "light-weight" proxy.
Now this is my result:
proxy.jsp:
<%@ page
import="java.io.*,
java.util.*,
java.net.*"
contentType="text/plain; charset=UTF-8"
%><%
StringBuffer sbf = new StringBuffer();
//Access the page
try {
// Add additional parameters to the requested url
String requestedUrl = request.getParameter("url");
Map<String,String> additionalParameters = request.getParameterMap();
Iterator parameterIterator = additionalParameters.keySet().iterator();
while( parameterIterator.hasNext() ) {
String nextParamName = (String) parameterIterator.next();
// no need to repeat "url" as this is our first and really mandatory request parameter
if ( !"url".equals(nextParamName) ) {
requestedUrl += "&"+nextParamName+"="+request.getParameter(nextParamName);
}
}
requestedUrl = requestedUrl.replace(" ","+");
URL url = new URL(requestedUrl);
HttpURLConnection conn=(HttpURLConnection)url.openConnection();
conn.setRequestMethod("GET");
String authHeaderValue = "Basic Y2x1c3RlcjpjbHVzdGVy";
conn.setRequestProperty("Authorization",authHeaderValue);
// Copy the proxied content-type to own response
response.setContentType(conn.getContentType());
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String inputLine;
while ( (inputLine = in.readLine()) != null) {
sbf.append(inputLine);
}
in.close();
} catch (MalformedURLException e) {
} catch (IOException e) {
}
%><%= sbf.toString()%>
To get the file directly, you can download it at github: proxy.jsp
After creating this JSP and putting it into the folder of one of the JBoss apps I registered this proxy-servlet inside the
web.xml of an existing app (in the example inside the "myapp" as to be seen in the jQuery-call below)
<servlet>
<servlet-name>proxy</servlet-name>
<jsp-file>/proxy.jsp</jsp-file>
</servlet>
<servlet-mapping>
<servlet-name>proxy</servlet-name>
<url-pattern>/proxy</url-pattern>
</servlet-mapping>
After re-deploying the JBoss app I was then able to use the Carte-service by using this kind of AJAX-Call:
$.ajax({
url : '/myapp/proxy?url=http://localhost:8888/kettle/executeTrans/?trans=getMeSomeData.ktr',
method : 'GET',
success: function(data) {
doSomethingWithTheData(data)
}
})
...which seems to be a more flexible and reuseable way to me of creating such proxy-requests without having to change the server-setup extensively.
Notes:
Upcoming in the next post I'd like to recreate the same approach for the PHP-Guys out there who would like to use Carte and PDI as JSON-Datasource in their PHP-applications.
Thanks for reading and best regards,
Tom
[Update]
The internet is great! Just some 16 hours after posting this blog I received feedback from another Pentaho-integrator (yes, that´s you Harris! ;-) ) claiming that the proxy did obviously default to "text/plain" as Content-Type, removing the possibility to properly deal with Carte's own "Status-Interfaces" (which are XML-Responses)
So now I am happy to present you version2 of my proxy.jsp, now with parameter and Content-Type support.
I would like to start off with a short "Thank you" to all of the Pentaho OpenSource-community
out there. Being a very responsive and supportive community I experienced a warm and healthy
environment ever since starting using the Pentaho BI-Suite (PDI, BI-Server and many of the infamous plugins) about 6 years ago.
This being said I would like to dive straight ahead into the post...
Lately I came across an intersting situation which this blogpost will talk about:
Making PDI/Carte-"services" available for other websites.
In short, this post will assume you to have some basic knowledge about:
- jQuery/AJAX requests/responses
- PDI and the Carte-slaveserver
To start, I would like to describe my intial problem, then display the solution I came up with while
being on-site at the customer.
As almost always, there´s many ways to solve a given problem, so please don't be picky about me if you and your solution are fit better for your needs.
Ok, now let´s go!
Problem
My situation was, to have the Carte-Service running on a given computer with also having a JBoss AS server deployed on another (or maybe the same) machine.
So we end up with Carte listening on http://localhost:8888 (Basic-Authentication active) and the
JBoss listening on http://localhost:8080 and having a bunch of apps deployed on the JBoss.
From inside one of these apps my goal was to access some KTRs on Carte via Web (e.g.: http://localhost:8888/kettle/executeTrans/?trans=getMeSomeData.ktr)
and return the data from the KTR to the requesting jQuery/AJAX call, which basically is something like this:
$.ajax({
url : 'http://localhost:8888/kettle/executeTrans/?trans=getMeSomeData.ktr',
method : 'GET',
success: function(data) {
doSomethingWithTheData(data)
}
})
However, having the originating request coming from localhost:8080 and requesting data from localhost:8888 causes an obvious problem:
"Crosssite scripting"!
Thus, jQuery requires you to use "CORS/JSONP" which just did not work for me.
Solution
So I ended up thinking about another approachand "proxy'ing" came to my mind.
In the end, I did some research and since I did not want to setup proxy-rules inside my JBoss I was looking for a more "light-weight" proxy.
Now this is my result:
proxy.jsp:
<%@ page
import="java.io.*,
java.util.*,
java.net.*"
contentType="text/plain; charset=UTF-8"
%><%
StringBuffer sbf = new StringBuffer();
//Access the page
try {
// Add additional parameters to the requested url
String requestedUrl = request.getParameter("url");
Map<String,String> additionalParameters = request.getParameterMap();
Iterator parameterIterator = additionalParameters.keySet().iterator();
while( parameterIterator.hasNext() ) {
String nextParamName = (String) parameterIterator.next();
// no need to repeat "url" as this is our first and really mandatory request parameter
if ( !"url".equals(nextParamName) ) {
requestedUrl += "&"+nextParamName+"="+request.getParameter(nextParamName);
}
}
requestedUrl = requestedUrl.replace(" ","+");
URL url = new URL(requestedUrl);
HttpURLConnection conn=(HttpURLConnection)url.openConnection();
conn.setRequestMethod("GET");
String authHeaderValue = "Basic Y2x1c3RlcjpjbHVzdGVy";
conn.setRequestProperty("Authorization",authHeaderValue);
// Copy the proxied content-type to own response
response.setContentType(conn.getContentType());
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String inputLine;
while ( (inputLine = in.readLine()) != null) {
sbf.append(inputLine);
}
in.close();
} catch (MalformedURLException e) {
} catch (IOException e) {
}
%><%= sbf.toString()%>
To get the file directly, you can download it at github: proxy.jsp
After creating this JSP and putting it into the folder of one of the JBoss apps I registered this proxy-servlet inside the
web.xml of an existing app (in the example inside the "myapp" as to be seen in the jQuery-call below)
<servlet>
<servlet-name>proxy</servlet-name>
<jsp-file>/proxy.jsp</jsp-file>
</servlet>
<servlet-mapping>
<servlet-name>proxy</servlet-name>
<url-pattern>/proxy</url-pattern>
</servlet-mapping>
After re-deploying the JBoss app I was then able to use the Carte-service by using this kind of AJAX-Call:
$.ajax({
url : '/myapp/proxy?url=http://localhost:8888/kettle/executeTrans/?trans=getMeSomeData.ktr',
method : 'GET',
success: function(data) {
doSomethingWithTheData(data)
}
})
...which seems to be a more flexible and reuseable way to me of creating such proxy-requests without having to change the server-setup extensively.
Notes:
- Please note that the default "cluster//cluster" credentials for the Carte-Service are "hard-coded" inside the proxy.jsp on line String authHeaderValue = "Basic Y2x1c3RlcjpjbHVzdGVy"; So if you need to/had changed that, check out http://decodebase64.com/ for a convenient site to create the new hash (enter them in the following format: <username>:<password>, e.g: cluster:cluster)
Upcoming in the next post I'd like to recreate the same approach for the PHP-Guys out there who would like to use Carte and PDI as JSON-Datasource in their PHP-applications.
Thanks for reading and best regards,
Tom
[Update]
The internet is great! Just some 16 hours after posting this blog I received feedback from another Pentaho-integrator (yes, that´s you Harris! ;-) ) claiming that the proxy did obviously default to "text/plain" as Content-Type, removing the possibility to properly deal with Carte's own "Status-Interfaces" (which are XML-Responses)
So now I am happy to present you version2 of my proxy.jsp, now with parameter and Content-Type support.
Abonnieren
Posts (Atom)