banniere

Le portail francophone de la géomatique


Toujours pas inscrit ? Mot de passe oublié ?
Nom d'utilisateur    Mot de passe              Toujours pas inscrit ?   Mot de passe oublié ?

#1 Tue 13 April 2010 10:35

topoman
Participant occasionnel
Date d'inscription: 22 Apr 2009
Messages: 19

[ArcGIS Server 9.3] flexviewer / webservice et proxy

Bonjour,

J'ai développé un widget se connectant a un webservice : http://www.caue-observatoire.fr/ws/ouvragesv2.asmx?wsdl
Ce service a été ajouté par le biais de flex builder DATA / import Web Service (WSDL)

Lorsque je teste ce développement en local tout marche impeccablement. Pour certaines raisons, flash ne permet pas l’execution et le chargement de certains fichiers provenant d’un domaine different de celui qui l’appel. Certains d’entre vous ce sont surement déjà retrouver “coincés” en voulant charger un flux rss distant dans un swf. la seule solution est soit d'avoir accès au domaine distant pour y déposer un fichier xml crossdomain ou soit de passer par un proxy.

Comme je n'ai pas accès au serveur distant je voudrais utiliser la méthode du proxy.

Dans la version 1.3 du flexviewer il est possible de configurer un proxy en ASP.

dans le fichier config.xml de l'application flexviewer le proxy est renseigné :

Code:

<proxytype>asp</proxytype>

et dans le fichier proxy.config :

Code:

<?xml version="1.0" encoding="utf-8" ?>
<!-- Proxy config is used to set the ArcGIS Server services that the proxy will forward to.        
        mustMatch: true to only proxy to sites listed, false to proxy to any site -->
<ProxyConfig mustMatch="true">
  <serverItems>
    <!-- serverUrl options:
            url = location of the ArcGIS Server, either specific URL or stem
            matchAll = true to forward any request beginning with the url
            token = (optional) token to include for token secured services, usually a long-term token
            tokenUrl = (optional) token service for a Web site (url)
            timeout = (optional) short-term timeout for a token in minutes
            username = (optional) username for a token or http secured site
            password = (optional) password for a token or http secured site
            domain = (optional) domain for an http secured site            
    
    <serverItem url="http://ns352902.ovh.net/ArcGIS/rest/services"
                  matchAll="true"
    
    />

    <serverItem url="http://www.caue-observatoire.fr/ws/ouvragesv2.asmx?wsdl"
                  matchAll="true" 
    
    />
-->
  </serverItems>
</ProxyConfig>

Mais cela ne fonctionne pas, quelqu'un a t il déjà réussi a faire ce paramétrage ? aucune aide détaillée n'est fournie sur le support esri, le problème peut-il venir de IIS ?

merci par avance pour vos suggestions.

Hors ligne

 

#2 Tue 13 April 2010 10:59

n314
Participant assidu
Date d'inscription: 6 Sep 2005
Messages: 704

Re: [ArcGIS Server 9.3] flexviewer / webservice et proxy

Coincé avec les mêmes problèmes pour une appli flex (non basée sur le flex viewer), j'ai résolu mon problème comme expliqué ici: http://www.forumsig.org/showthread.php?t=26586

la balise proxy de config.xml et le fichier proxy.config servent (de ce que j'ai compris du flex viewer) uniquement à configurer l'application flash/flex pour utiliser un proxy.

Le proxy est donc à construire+déployer afin de l'utiliser... Creuser dans ce sens, pour trouver la page asp servant de proxy et la tester séparément de votre application.

Dernière modification par n314 (Tue 13 April 2010 11:00)

Hors ligne

 

#3 Tue 13 April 2010 14:42

topoman
Participant occasionnel
Date d'inscription: 22 Apr 2009
Messages: 19

Re: [ArcGIS Server 9.3] flexviewer / webservice et proxy

pas évident, cette notion de proxy !

à la racine de l'app flex j'ai ce fichier :

proxy.ashx

Code:

<%@ WebHandler Language="C#" Class="proxy" %>
/*
  This proxy page does not have any security checks. It is highly recommended
  that a user deploying this proxy page on their web server, add appropriate
  security checks, for example checking request path, username/password, target
  url, etc.
*/
using System;
using System.Drawing;
using System.IO;
using System.Web;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;
using System.Web.Caching;
using System.Net;
using System.Security.Cryptography.X509Certificates;


/// <summary>
/// Forwards requests to an ArcGIS Server REST resource. Uses information in
/// the proxy.config file to determine properties of the server.
/// </summary>
public class proxy : IHttpHandler
{
    public void ProcessRequest(HttpContext context)
    {
        HttpResponse response = context.Response;

        // Get the URL requested by the client (take the entire querystring at once
        //  to handle the case of the URL itself containing querystring parameters)
        string uri = Uri.UnescapeDataString(context.Request.QueryString.ToString());

        // Debug: Ping to make sure avaiable (ie. http://localhost/TestApp/proxy.ashx?ping)
        if (uri.StartsWith("ping"))
        {
            context.Response.Write("Hello proxy");
            return;
        }
        
        // Get token, if applicable, and append to the request
        string token = getTokenFromConfigFile(uri);
        System.Net.ICredentials credentials = null;

        if (string.IsNullOrEmpty(token))
            token = generateToken(uri);

        if (!String.IsNullOrEmpty(token))
        {
            if (uri.Contains("?"))
                uri += "&token=" + token;
            else
                uri += "?token=" + token;
        }
        else // if using Windows/HTTP authentication
        {
            credentials = getCredentials(uri);
        }

        System.Net.WebRequest req = System.Net.WebRequest.Create(new Uri(uri));
        req.Method = context.Request.HttpMethod;
                
        // Assign credentials if using Windows/HTTP authentication
        if (credentials != null)
        {
            req.PreAuthenticate = true;
            req.Credentials = credentials;
        }

        // Set body of request for POST requests
        if (context.Request.InputStream.Length > 0)
        {
            byte[] bytes = new byte[context.Request.InputStream.Length];
            context.Request.InputStream.Read(bytes, 0, (int)context.Request.InputStream.Length);
            req.ContentLength = bytes.Length;
            req.ContentType = "application/x-www-form-urlencoded";
            using (Stream outputStream = req.GetRequestStream())
            {
                outputStream.Write(bytes, 0, bytes.Length);
            }
        }

        // Send the request to the server
        System.Net.WebResponse serverResponse = null;
        try
        {
            serverResponse = req.GetResponse();
        }
        catch (System.Net.WebException webExc)
        {
            response.StatusCode = 500;
            response.StatusDescription = webExc.Status.ToString();
            response.Write(webExc.Response);
            response.End();
            return;
        }

        // Set up the response to the client
        if (serverResponse != null)
        {
            response.ContentType = serverResponse.ContentType;
            using (Stream byteStream = serverResponse.GetResponseStream())
            {
                // Text response
                if (serverResponse.ContentType.Contains("text"))
                {
                    using (StreamReader sr = new StreamReader(byteStream))
                    {
                        string strResponse = sr.ReadToEnd();
                        response.Write(strResponse);
                    }
                }
                else
                {
                    const int BUFFER_SIZE = 1024 * 1024;
                    using (System.IO.Stream stream = serverResponse.GetResponseStream())
                    {
                        byte[] bytes = new byte[BUFFER_SIZE];
                        while (true)
                        {
                            int n = stream.Read(bytes, 0, BUFFER_SIZE);
                            if (n == 0) break;
                            response.OutputStream.Write(bytes, 0, n);
                        }
                    }
          
                    // Tell client not to cache the image since it's dynamic
                    response.CacheControl = "no-cache";
                }

                serverResponse.Close();
            }
        }
        response.End();
    }

    public bool IsReusable
    {
        get
        {
            return false;
        }
    }

    // Gets the token for a server URL from a configuration file
    private string getTokenFromConfigFile(string uri)
    {
        try
        {
            ProxyConfig config = ProxyConfig.GetCurrentConfig();
            if (config != null)
                return config.GetToken(uri);
            else
                throw new ApplicationException(
                    "Proxy.config file does not exist at application root, or is not readable.");
        }
        catch (InvalidOperationException)
        {
            // Proxy is being used for an unsupported service (proxy.config has mustMatch="true")
            HttpResponse response = HttpContext.Current.Response;
            response.StatusCode = (int)System.Net.HttpStatusCode.Forbidden;
            response.End();
        }
        catch (Exception e)
        {
            if (e is ApplicationException)
                throw e;

            // just return an empty string at this point
            // -- may want to throw an exception, or add to a log file
        }

        return string.Empty;
    }

    public System.Net.ICredentials getCredentials(string url)
    {
        try
        {
            ProxyConfig config = ProxyConfig.GetCurrentConfig();
            if (config != null)
            {
                foreach (ServerItem si in config.ServerItems)
                    if (url.StartsWith(si.Url, true, null))
                    {
                         string url_401 = url.Substring(0, url.IndexOf("Server") + 6);                         

                        if (HttpRuntime.Cache[url_401] == null)
                        {
                            HttpWebRequest webRequest_401 = null;
                            webRequest_401 = (HttpWebRequest)HttpWebRequest.Create(url_401);
                            webRequest_401.ContentType = "text/xml;charset=\"utf-8\"";
                            webRequest_401.Method = "GET";
                            webRequest_401.Accept = "text/xml";

                            HttpWebResponse webResponse_401 = null;
                            while (webResponse_401 == null || webResponse_401.StatusCode != HttpStatusCode.OK)
                            {
                                try
                                {
                                    webResponse_401 = (System.Net.HttpWebResponse)webRequest_401.GetResponse();
                                    System.Net.HttpWebResponse webexResponse = webResponse_401; // (HttpWebResponse)webex.Response;
                                    //if (webexResponse.StatusCode == HttpStatusCode.Unauthorized)
                                    //{
                                        if (webRequest_401.Credentials == null)
                                        {
                                            webRequest_401 = (HttpWebRequest)HttpWebRequest.Create(url_401);
                                            webRequest_401.Credentials =
                                                new System.Net.NetworkCredential(si.Username, si.Password, si.Domain);
                                        }
                                       
                                    //}
                                }
                                catch (System.Net.WebException webex)
                                {
                                    System.Net.HttpWebResponse webexResponse = (HttpWebResponse)webex.Response;
                                    if (webexResponse.StatusCode == HttpStatusCode.Unauthorized)
                                    {
                                        if (webRequest_401.Credentials == null)
                                        {
                                            webRequest_401 = (HttpWebRequest)HttpWebRequest.Create(url_401);
                                            webRequest_401.Credentials =
                                                new System.Net.NetworkCredential(si.Username, si.Password, si.Domain);
                                        }
                                        else // if original credentials not accepted, throw exception                                        
                                            throw webex;
                                    }
                                    else // if status code unrecognized, throw exception                                          
                                        throw webex;
                                }
                                catch (Exception ex) { throw ex; }
                            }

                            if (webResponse_401 != null)
                                webResponse_401.Close();

                            HttpRuntime.Cache.Insert(url_401, webRequest_401.Credentials);
                        }
                        return (ICredentials)HttpRuntime.Cache[url_401];
                    }
            }
        }
        catch (InvalidOperationException)
        {
            // Proxy is being used for an unsupported service (proxy.config has mustMatch="true")
            HttpResponse response = HttpContext.Current.Response;
            response.StatusCode = (int)System.Net.HttpStatusCode.Forbidden;
            response.End();
        }
        catch (Exception e)
        {
            if (e is ApplicationException)
                throw e;

            // just return an empty string at this point
            // -- may want to throw an exception, or add to a log file
        }

        return null;
    }

    public string generateToken(string url)
    {
        try
        {
            ProxyConfig config = ProxyConfig.GetCurrentConfig();
            if (config != null)
            {
                foreach (ServerItem si in config.ServerItems)
                    if (url.StartsWith(si.Url, true, null))
                    {
                        string theToken = null;

                        // If a token has been generated, check the expire time
                        if (HttpRuntime.Cache[si.Url] != null)
                        {
                            string existingToken = (HttpRuntime.Cache[si.Url] as
                            Dictionary<string, object>)["token"] as string;

                            DateTime expireTime = (DateTime)((HttpRuntime.Cache[si.Url] as
                            Dictionary<string, object>)["timeout"]);

                            // If token not expired, return it
                            if (DateTime.Now.CompareTo(expireTime) < 0)
                                theToken = existingToken;
                        }

                        // If token not available or expired, generate one and store it in cache
                        if (theToken == null)
                        {
                            string tokenServiceUrl = string.Format("{0}?request=getToken&username={1}&password={2}",
                                si.TokenUrl, si.Username, si.Password);
                            
                            int timeout = 60;
                            if (si.Timeout > 0)
                                timeout = si.Timeout;

                            tokenServiceUrl += string.Format("&expiration={0}", timeout);
                            DateTime endTime = DateTime.Now.AddMinutes(timeout);
                            
                            System.Net.ServicePointManager.CertificatePolicy = new MyPolicy();
                            System.Net.WebRequest request = System.Net.WebRequest.Create(tokenServiceUrl);
                            System.Net.WebResponse response = null;
                            try
                            {
                                 response = request.GetResponse();
                            }
                            catch (Exception e)
                            {
                            }
                            System.IO.Stream responseStream = response.GetResponseStream();
                            System.IO.StreamReader readStream = new System.IO.StreamReader(responseStream);
                            theToken = readStream.ReadToEnd();

                            Dictionary<string, object> serverItemEntries = new Dictionary<string, object>();
                            serverItemEntries.Add("token", theToken);
                            serverItemEntries.Add("timeout", endTime);

                            HttpRuntime.Cache.Insert(si.Url, serverItemEntries);
                        }
                        return theToken;
                    }
            }
        }
        catch (InvalidOperationException)
        {
            // Proxy is being used for an unsupported service (proxy.config has mustMatch="true")
            HttpResponse response = HttpContext.Current.Response;
            response.StatusCode = (int)System.Net.HttpStatusCode.Forbidden;
            response.End();
        }
        catch (Exception e)
        {
            if (e is ApplicationException)
                throw e;

            // just return an empty string at this point
            // -- may want to throw an exception, or add to a log file
        }

        return string.Empty;
    }
}

[XmlRoot("ProxyConfig")]
public class ProxyConfig
{
    #region Static Members

    private static object _lockobject = new object();

    public static ProxyConfig LoadProxyConfig(string fileName)
    {
        ProxyConfig config = null;

        lock (_lockobject)
        {
            if (System.IO.File.Exists(fileName))
            {
                XmlSerializer reader = new XmlSerializer(typeof(ProxyConfig));
                using (System.IO.StreamReader file = new System.IO.StreamReader(fileName))
                {
                    config = (ProxyConfig)reader.Deserialize(file);
                }
            }
        }

        return config;
    }

    public static ProxyConfig GetCurrentConfig()
    {
        ProxyConfig config = HttpRuntime.Cache["proxyConfig"] as ProxyConfig;
        if (config == null)
        {
            string fileName = GetFilename(HttpContext.Current);
            config = LoadProxyConfig(fileName);

            if (config != null)
            {
                CacheDependency dep = new CacheDependency(fileName);
                HttpRuntime.Cache.Insert("proxyConfig", config, dep);
            }
        }

        return config;
    }

    // Location of the proxy.config file
    public static string GetFilename(HttpContext context)
    {
        return context.Server.MapPath("~/proxy.config");
    }
    #endregion

    ServerItem[] serverItems;
    bool mustMatch;

    [XmlArray("serverItems")]
    [XmlArrayItem("serverItem")]
    public ServerItem[] ServerItems
    {
        get { return this.serverItems; }
        set { this.serverItems = value; }
    }

    [XmlAttribute("mustMatch")]
    public bool MustMatch
    {
        get { return mustMatch; }
        set { mustMatch = value; }
    }

    public string GetToken(string uri)
    {
        foreach (ServerItem su in serverItems)
        {
            if (su.MatchAll && uri.StartsWith(su.Url, StringComparison.InvariantCultureIgnoreCase))
            {
                return su.Token;
            }
            else
            {
                if (String.Compare(uri, su.Url, StringComparison.InvariantCultureIgnoreCase) == 0)
                    return su.Token;
            }
        }

        if (mustMatch)
            throw new InvalidOperationException();

        return string.Empty;
    }
}

public class ServerItem
{
    string url;
    bool matchAll;
    string token;
    string tokenUrl;
    string domain;
    string username;
    string password;
    int timeout;

    [XmlAttribute("url")]
    public string Url
    {
        get { return url; }
        set { url = value; }
    }

    [XmlAttribute("matchAll")]
    public bool MatchAll
    {
        get { return matchAll; }
        set { matchAll = value; }
    }

    [XmlAttribute("token")]
    public string Token
    {
        get { return token; }
        set { token = value; }
    }

    [XmlAttribute("tokenUrl")]
    public string TokenUrl
    {
        get { return tokenUrl; }
        set { tokenUrl = value; }
    }

    [XmlAttribute("domain")]
    public string Domain
    {
        get { return domain; }
        set { domain = value; }
    }

    [XmlAttribute("username")]
    public string Username
    {
        get { return username; }
        set { username = value; }
    }

    [XmlAttribute("password")]
    public string Password
    {
        get { return password; }
        set { password = value; }
    }

    [XmlAttribute("timeout")]
    public int Timeout
    {
        get { return timeout; }
        set { timeout = value; }
    }
}


public class MyPolicy : ICertificatePolicy {
    public bool CheckValidationResult(
          ServicePoint srvPoint
        , X509Certificate certificate
        , WebRequest request
        , int certificateProblem) {

        //Return True to force the certificate to be accepted.
        return true;

    } // end CheckValidationResult
} // class MyPolicy

C'est ce fichier qui va me permettre de déployer le proxy ?

Hors ligne

 

#4 Tue 13 April 2010 15:15

n314
Participant assidu
Date d'inscription: 6 Sep 2005
Messages: 704

Re: [ArcGIS Server 9.3] flexviewer / webservice et proxy

Voui, tout à fait. Il faut lire la doc fournie avec le flexviewer ou trainer sur les forums esri pour comprendre comment paramétrer...

grosso modo, si votre site est bien configuré, l'url http://monserveur/monappli/proxy.ashx renverra autre chose qu'une erreure 404. Si tout est bien configuré, l'url http://monserveur/monappli/proxy.ashx?http://goerezon.net devrait marcher... (peut être bizarrement, ie les css et images en chemin relatif par exemple seront absents).

Hors ligne

 

#5 Tue 13 April 2010 16:21

topoman
Participant occasionnel
Date d'inscription: 22 Apr 2009
Messages: 19

Re: [ArcGIS Server 9.3] flexviewer / webservice et proxy

ok, je vais regarder ça !!!

il a l'air de fonctionner : http://ns352902.ovh.net/testflex3/proxy.ashx?ping

http://ns352902.ovh.net/testflex3/proxy … eorezo.net


par contre dans le widget dois je préciser que le webservice passe par ce proxy (webservice.proxy = "true") ?

car le container (flexviewer) redirige peut être automatiquement !

encore merci !

Dernière modification par topoman (Tue 13 April 2010 16:39)

Hors ligne

 

#6 Tue 13 April 2010 16:56

n314
Participant assidu
Date d'inscription: 6 Sep 2005
Messages: 704

Re: [ArcGIS Server 9.3] flexviewer / webservice et proxy

ca semble effectivement fonctionner.

par contre dans le widget dois je préciser que le webservice passe par ce proxy (webservice.proxy = "true")
-> je dirais que oui

-> attention à être précautionneux avec la config de proxy.config, notamment la propriité <ProxyConfig mustMatch="true"> qui indique que le proxy ne sera actif que pour les services listés (à configurer également) et rejettera toutes les connections à un serveur non listé

-> penser également à protéger le proxy, à voir avec le sys admin.

Hors ligne

 

#7 Wed 14 April 2010 13:24

topoman
Participant occasionnel
Date d'inscription: 22 Apr 2009
Messages: 19

Re: [ArcGIS Server 9.3] flexviewer / webservice et proxy

ok merci pour les conseils !!!

mais le service web que j'utilise a été importé par le biais de la fonction data / import webservices et lorsque je le déclare dans mon application il n'est pas possible de spécifier l'usage du proxy(useproxy="true") .... comme lorsqu'on utilise un httpservice.

J'ai utilisé Fiddler pour tracer les requêtes http de l'application, résultat : je m'aperçois que les fonds de cartes sont bien appelés par l'intermédiaire du proxy mais mon webservice continu de demander le fichier crossdomain du serveur distant.

Je pense que la solution est de ne pas passer par la fonction d'importation automatique d'un webservice mais de le déclarer manuellement à l'aide d'une balise httpservice. Mais là je suis bloqué par la syntaxe :


Code:

<mx:HTTPService id="MonService" 
    url="http://www.caue-observatoire.fr/ws/ouvragesv2.asmx">
    useProxy="true"
</mx:HTTPService>

je voudrais utiliser la fonction de recherche libre disponible sur http://www.caue-observatoire.fr/ws/ouvr … =Recherche .

Avant j'utilisais cette méthode :


             

Code:

 
                import fr.caueobservatoire.Recherche_request;
        import fr.caueobservatoire.RechercheResultEvent;
        import fr.caueobservatoire.OuvragesV2;

                public var MonService:OuvragesV2 = new OuvragesV2;
        public var Monresultat:XML = new XML;
        public var MesImages:XML = new XML;
        [Bindable]private var lms_list:XMLList;


                private function CallService():void{
        MonService.addrechercheEventListener(handelResult);
        MonService.recherche(-1,"","","","","",59,"","",-1,-1,-1,-1);
        cursorManager.setBusyCursor();
        }
        
        private function handelResult (event:RechercheResultEvent):void{
            cursorManager.removeBusyCursor();
            Monresultat = new XML(event.result);
            textservice.text = Monresultat.toXMLString();
            lms_list = Monresultat.children();
        }

Hors ligne

 

Pied de page des forums

Powered by FluxBB