Using Attachment Editor With a Proxy

3050
10
12-22-2010 09:37 AM
WilliamDonahue
New Contributor
I have been using the attachment editor for a while now. Once i added a proxy to all my rest layers... the attachment editor still allows me to view and delete attachments, however on the downside I can not add attachments i keep getting an error stating:

is not a valid JSON primitive. This error can also occur when extraneous data is present after the JSON data.

If i remove the proxy it will allow the data to pass however the proxy is part of my security.
0 Kudos
10 Replies
WilliamDonahue
New Contributor
I have spent the past hour and a half working on this and it still hasn't cleared...Using fiddler/Firebug i have determined that the REST endpoint doesn't return the standard script of
[HTML]{"addAttachmentResult":{"objectId":5,"globalId" : null,"success":true}}[/HTML]

It instead returns the entrie REST add attachment page...

I have cross checked everything and i don't see why this isn't working. It will delete through the proxy it just appears to not accept the data when i am posting. i find this strange because i can add points to the map just fine and edit attributes.

My proxy code is as follows:

[PHP]<?php
    /***************************************************************************
   * USAGE
   * [1] http://<this-proxy-url>?<arcgis-service-url>
   * [2] http://<this-proxy-url>?<arcgis-service-url> (with POST body)
   * [3] http://<this-proxy-url>?<arcgis-service-url>?token=ABCDEFGH
   *
   * note: [3] is used when fetching tiles from a secured service and the
   * JavaScript app sends the token instead of being set in this proxy
   *
   * REQUIREMENTS
   *  - cURL extension for PHP must be installed and loaded. To load it,
   *    add the following lines to your php.ini file:
   *     extension_dir = "<your-php-install-location>/ext"
   *     extension = php_curl.dll
   *    
   *  - Turn OFF magic quotes for incoming GET/POST data: add/modify the
   *    following line to your php.ini file:
   *     magic_quotes_gpc = Off
   *
   ***************************************************************************/

  /***************************************************************************
   * <true> to only proxy to the sites listed in '$serverUrls'
   * <false> to proxy to any site (are you sure you want to do this?)
   */
  $mustMatch = true;
 
  /***************************************************************************
   * ArcGIS Server services this proxy will forward requests to
   *
   * 'url'      = location of the ArcGIS Server, either specific URL or stem
   * 'matchAll' = <true> to forward any request beginning with the URL
   *              <false> to forward only the request that exactly matches the url
   * 'token'    = token to include for secured service, if any, otherwise leave it
   *              empty
   */
  $serverUrls = array(
    array( 'url' => 'http://<server>/ArcGIS/rest/services/', 'matchAll' => true,  'token' => '' ),
    array( 'url' => 'http://<server>//ArcGIS/rest/services/CBGrounding/FeatureServer/0', 'matchAll' => true,  'token' => ''   ),
    //array( 'url' => 'http://<server>//ArcGIS/rest/services/CBFaceplate/FeatureServer',        'matchAll' => true, 'token' => '' ),
    //array( 'url' => 'http://<server>//ArcGIS/rest/services/CBPower/FeatureServer',        'matchAll' => true, 'token' => '' ),
    //array( 'url' => 'http://<server>//ArcGIS/rest/services/CBGrounding/MapServer',        'matchAll' => true, 'token' => '' ),
   
  );
  /***************************************************************************/
 
  function is_url_allowed($allowedServers, $url) {
    $isOk = false;
    $url = trim($url);
    for ($i = 0, $len = count($allowedServers); $i < $len; $i++) {
      $value = $allowedServers[$i];
      $allowedUrl = trim($value['url'], "\/");
      if ($value['matchAll']) {
        if (stripos($url, $allowedUrl) === 0) {
          $isOk = $i; // array index that matched
          break;
        }
      }
      else {
        if ((strcasecmp($url, $allowedUrl) == 0)) {
          $isOk = $i; // array index that matched
          break;
        }
      }
    }
    return $isOk;
  }
 
  // check if the curl extension is loaded
  if (!extension_loaded("curl")) {
    header('Status: 500', true, 500);
    echo 'cURL extension for PHP is not loaded! <br/> Add the following lines to your php.ini file: <br/> extension_dir = &quot;&lt;your-php-install-location&gt;/ext&quot; <br/> extension = php_curl.dll';
    return;
  }
 
  $targetUrl = $_SERVER['QUERY_STRING'];
  if (!$targetUrl) {
    header('Status: 400', true, 400); // Bad Request
    echo 'Target URL is not specified! <br/> Usage: <br/> http://<this-proxy-url>?<target-url>';
    return;
  }
  $targetUrl= rawurldecode($targetUrl);
  $urlex=explode('export?',$targetUrl);
  $urlex2=explode('query?',$urlex[0]);
  $parts = preg_split("/\?/", $urlex2[0]);
 
  $targetPath = $parts[0];
 
  // check if the request URL matches any of the allowed URLs
  if ($mustMatch) {
  
    $isOk = false;
    $url = trim($targetPath, "\/");
    for ($i = 0, $len = count($serverUrls); $i < $len; $i++) {
      $value = $serverUrls[$i];
      $allowedUrl = trim($value['url'], "\/");
      if ($value['matchAll']) {
        if (stripos($url, $allowedUrl) === 0) {
          $isOk = $i; // array index that matched
          break;
        }
      }
      else {
        if ((strcasecmp($url, $allowedUrl) == 0)) {
          $isOk = $i; // array index that matched
          break;
        }
      }
    }
    $pos = $isOk;
 

   
    if ($pos === false) {
      header('Status: 403', true, 403); // Forbidden
      echo 'Target URL is not allowed! <br/> Consult the documentation for this proxy to add the target URL to its Whitelist.';
      print "<br/>url is $url <br/>";
      print "allowedurl is $allowedUrl <br/>";
      print "targeturl is $targetUrl <br/>";
      print "targetpath is $targetPath <br/>";
      print "<br/>path 0 is {$parts[0]} <br/>";
   print "<br/>path 2 is {$parts[2]} <br/>";
      return;
    }
  }
 
  // add token (if any) to the url
  $token = $serverUrls[$pos]['token'];
  if ($token) {
    $targetUrl .= (stripos($targetUrl, "?") !== false ? '&' : '?').'token='.$token;
  }
 
  // open the curl session
  $session = curl_init();
 
  // set the appropriate options for this request
  $options = array(
    CURLOPT_URL => $targetUrl,
    CURLOPT_HEADER => false,
    CURLOPT_HTTPHEADER => array(
      'Content-Type: ' . $_SERVER['CONTENT_TYPE'],
      'Referer: ' . $_SERVER['HTTP_REFERER']
    ),
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_FOLLOWLOCATION => true
  );
 
  // put the POST data in the request body
  $postData = file_get_contents("php://input");
  if (strlen($postData) > 0) {
    $options[CURLOPT_POST] = true;
    $options[CURLOPT_POSTFIELDS] = $postData;
  }
  curl_setopt_array($session, $options);
 
  // make the call
  $response = curl_exec($session);
  $code = curl_getinfo($session, CURLINFO_HTTP_CODE);
  $type = curl_getinfo($session, CURLINFO_CONTENT_TYPE);
  curl_close($session);
 
  // set the proper Content-Type
  header("Status: ".$code, true, $code);
  header("Content-Type: ".$type);


  echo $response;
?>
[/PHP]

Let me know if anyone sees what is going on.
0 Kudos
WilliamDonahue
New Contributor
Hey guys... again.

So i found out why it is not working now but i don't know how to fix it.

When the esri attachemnt editor sends an add attachment to the system it does not offcially use the f=json& at the end of the line. This means that is not recognized by my proxy or most likely many others. Is there anyway for the rest endpoint to use my proxy and and perform attachment tasks.

I have tried the ESRI silverlight ASP.NET proxy as well as my modified php proxy from the javascript side of things. neither of them recognize this error.
0 Kudos
DarrinBlaisdell
New Contributor II
I am struggling with a similar issue to what you describe.  Did you ever figure out a solution?

Thanks in advance...
0 Kudos
by Anonymous User
Not applicable
Thank you for reporting this issue.  The problem appears to be that our PHP proxy relies on getting the request body from the PHP input and output stream.  However, I'm pretty sure the attachment request header encodes file uploads as "multipart/form-data". 

Unfortunately, this type of file encoding does work with PHP input and output streams and a bug has been logged.

Regards,
Doug Carroll, ESRI Support Services SDK / UAG Team
http://support.esri.com/
0 Kudos
by Anonymous User
Not applicable
For those following this post I revised the PHP proxy so it handles attachments.  The proxy page is zipped and attached to this thread. 

Regards,
Doug Carroll, ESRI Support Services SDK Team
http://support.esri.com/
0 Kudos
ShonHarper
New Contributor II
Hi,

So I am trying  this (proxy_sl.php) on a development server and it is still not working for file upload...

I have created an upload directory, given everyone rwx permissions (bad practice as is the location under the web root but this is a dev box and I had to move forward for now..) and edited proxy_sl.php as follows:

$upload_path = "/services/web/webapps/uploads";
  $allowed_mime_type_files = array("video/quicktime", "image/bmp", "image/tiff", "image/png","image/jpeg");


I am trying to add and attachment (.jpg) using the attachment editor (javascript api).

Am I missing something here?

Thanks!
0 Kudos
ShonHarper
New Contributor II
Disregard for the time being.  I believe I have some temp directory permission issues going on.

Thank you.
0 Kudos
DarrinBlaisdell
New Contributor II
Doug,

I am using the updated php proxy you provided in this thread with the attachment editor widget. I have run into, what I believe, is a side effect of the fix in the proxy.


Notice: Undefined index: CONTENT_TYPE in /services/web/proxy.php on line 174 Notice: Undefined index: HTTP_REFERER in /services/web/proxy.php on line 175
ArcGIS Services Directory


Effectively, I can't access my secure feature service in the application via the proxy and the supplied token.

Any chance you can look further into this issue?

Thanks,

Darrin
0 Kudos
ShonHarper
New Contributor II
Doug,

I am having trouble getting this proxy.php to pass a token when doing a POST request.  Any ideas?

Thanks.
0 Kudos