#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: 706
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: 706
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: 706
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