CURL: simple proxy script won't post data my way

I am trying to make a simple script in php using curl to work as a proxy for my javascript (OpenLayers) requests to a WFS server on a different domain. It looks like this:


$url=$_REQUEST['url']; 
$post='<wfs:GetFeature xmlns:wfs="http://www.opengis.net/wfs" service="WFS" version="1.1.0" xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.1.0/wfs.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><wfs:Query typeName="feature:Bomen" srsName="EPSG:28992" xmlns:feature="http://bor.grontmij.nl/haarlemmermeer"><ogc:Filter xmlns:ogc="http://www.opengis.net/ogc"><ogc:BBOX><ogc:PropertyName>GEOMETRIE</ogc:PropertyName><gml:Envelope xmlns:gml="http://www.opengis.net/gml" srsName="EPSG:28992"><gml:lowerCorner>107462.72 480068.8</gml:lowerCorner><gml:upperCorner>107644.16 480209.92</gml:upperCorner></gml:Envelope></ogc:BBOX></ogc:Filter></wfs:Query></wfs:GetFeature>';
if (isset($HTTP_RAW_POST_DATA)) {$post=$HTTP_RAW_POST_DATA;}; //else {$post='none';};
$ch = curl_init($url); //.'?request=GetCapabilities'
$postfields=array('filter' => urlencode($post) );
$postfields=array('' => urlencode($post) );
$postfields=array( urlencode($post) );
//file_put_contents ( 'tmp.txt' , $post );
//$postfields=array('file'=>'@tmp.txt');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields);
//curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch, CURLINFO_HEADER_OUT, true );
$content = curl_exec( $ch );
$response = curl_getinfo( $ch );
curl_close ( $ch );
echo "url: ".$url.'<br/><hr/>';
echo '$HTTP_RAW_POST_DATA: <pre>'.htmlentities($post).'</pre><pre>'.urlencode($post).'</pre><hr/>';
echo '<br/> $content: <pre>'.htmlentities((String)$content).'</pre><hr/>';
foreach($response as $key => $r) {
  echo '<pre>$response["'.$key.'"]: '.htmlentities((String)$r).'</pre><hr/>';
};

As you can see above, I have tried out a number of different options.

This is how a WFS standard works and how the OpenLayers WFS protocol class sends the request*. The WFS request is posted - not as key value pairs, but simply as a piece of xml - which I can inspect with Firebug. And it works fine when those requests are sent via OpenLayers (i.e. javascript) directly to a WFS service on the same domain as the rest of my page. But not when sent to my php proxy script and from there to a foreign domain.

It seems as if the CURL functions are only designed for posting key value pairs. If I try to send the xml string as so:

curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
curl_setopt($ch, CURLOPT_POSTFIELDS, urlencode($post));

I get an exception from the service:

Could not determine geoserver request from http request org.apache.catalina.connector.RequestFacade@6e2752

If I post it as a “normal” array, I get a “Bad request”:

$postfields=array( urlencode($post) );

If I post it as an associative array like one of these options:

$postfields=array(‘filter’ => urlencode($post) );
$postfields=array(‘’ => urlencode($post) );

I get (naturally) this error from the service:

org.xmlpull.v1.XmlPullParserException: only whitespace content allowed before start tag and not - (position: START_DOCUMENT seen -… @1:1)
only whitespace content allowed before start tag and not - (position: START_DOCUMENT seen -… @1:1)

I am sure this is possible somehow. What am I doing wrong …?!?

/jonas :confused:

Hellooo! Anybody out there?
Sure someone has an idea about what to do?

Sounds like you have already done this but here goes anyway. But first a question, if the WFS is indeed posted, they must be looking for the first element of the array, is there a possibility the are looking for something like xml=$post.

I know nothing about WFS but after looking at some documentation it sure sounds like you need a name value pair thing going on.
I found this in an example “DescribeFeatureType?version=1.1.0&typename=og:restricted” which is a $_GET request.

All I have is try this, take it down to the basics and just send your $post string.


$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS,"$post");
$result= curl_exec ($ch);
curl_close ($ch);
echo $result;

cURL AFAIK doesn’t really care about name value pairs but $post will be $_POSTed, it should just send the data as the first element of the array.

Try that and see what $result is. I don’t know how your $url process things but try manually going to the url like this,
placeToSendXML.com? with your $post string after the question mark, this will still be interpreted as an array.

I’m pretty sure you need a $key for your $post data.

Thanks a bundle @lorenw, I shall try this out within the next couple of days and post the result here :slight_smile:

Hi - Did you ever get this working?

Thanks,
Steve

No, sorry - I never got back to this issue as we had other more important issues in the project, that I am working on. This issue is a nice-to-have, while many others were need-to-have issues.

Originally, I tried to solve this with an Apache proxy script - and as I couldn’t make that work, I thought it would be easier for me to do in PHP.

Browsers and javascript do not allow cross-domain XMLHTTP-requests and therefor WFS requests from a map application must go to the page’s domain. Consequently, I you want to request data from other WFS data sources, you must let the page domain work as a proxy.

The project I work on currently only uses WFS data from its own domain. The reason I needed it, was to set up a javascript development environment on my own localhost - without having to set up the entire database, geoserver etc on my localhost as well - as I am a front end developer.

Hi Jonas,
Thanks for the reply.

In the meantime I did get this working - and am very pleased with the results. Once I get the reply back I use simplexml function to parse the reply into an array which I then display on Google maps.

If I remember correctly, all I was doing wrong was not sending the correct headers (the httpheaders in the code below).

Heres my code if it helps. I think the variable names are fairly clear.


//*************************************************************************************************************
	
//Set CURL parameters.
$var_wfs_url = $var_wfs_workspaces[$var_workspace]['url']; //Get the WFS URL

$ch = curl_init();
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_URL, $var_wfs_url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: text/xml', 'Content-Length: ' . strlen($var_wfs_query)));
curl_setopt($ch, CURLOPT_POSTFIELDS, $var_wfs_query);

//Run the query
$var_wfs_reply = curl_exec($ch);

$var_results_string = $var_wfs_reply;
//echo "WFS result: " . $var_results_string . "<br /><br />";

//Close the connection.
curl_close ($ch);
		
//************************************************************************************************************

Hope that helps!

Steve