{"id":125,"date":"2010-06-23T00:12:48","date_gmt":"2010-06-22T23:12:48","guid":{"rendered":"http:\/\/capri.dev\/blog\/?p=125"},"modified":"2010-06-23T16:52:24","modified_gmt":"2010-06-23T15:52:24","slug":"opciones-disponibles-para-aplicaciones-web-que-necesitan-geoposicionamiento","status":"publish","type":"post","link":"https:\/\/capri.dev\/blog\/opciones-disponibles-para-aplicaciones-web-que-necesitan-geoposicionamiento\/","title":{"rendered":"Opciones disponibles para aplicaciones web que necesitan geoposicionamiento"},"content":{"rendered":"<p>Hace poco estuve trabajando en la web <a href=\"http:\/\/www.afterguantanamo.com\">afterguantanamo.com<\/a> y uno de los requisitos que quer\u00edamos cubrir era la posibilidad de tener la web en varios idiomas y que en funci\u00f3n del pa\u00eds desde el que se visitase (despu\u00e9s de todo se trata de un tema internacional), la web se mostrase en un idioma o en otro de manera autom\u00e1tica. Para conseguirlo era necesario utilizar alg\u00fan sistema de geoposicionamiento, por lo que me puse a investigar las opciones disponibles.<\/p>\n<p>Despu\u00e9s de mirar por aqu\u00ed y por all\u00e1, encontr\u00e9 que el servicio de <a href=\"http:\/\/www.wipmania.com\">wipmania.com<\/a> era una soluci\u00f3n r\u00e1pida bastante f\u00e1cil de implementar que no exig\u00eda pr\u00e1cticamente ning\u00fan esfuerzo. Adem\u00e1s, el servicio es gratuito, lo que lo hizo una elecci\u00f3n muy sencilla respecto a otras soluciones de pago. <strong>Para utilizar este servicio no hay m\u00e1s que pasar a su servidor la consulta con la IP de la que queremos averiguar el pa\u00eds, y este nos devuelve un c\u00f3digo de 2 caracteres que representa de forma un\u00edvoca a cada pa\u00eds<\/strong>. En principio, la consulta s\u00f3lo se puede realizar a trav\u00e9s de un m\u00e9todo GET con el formato<\/p>\n<p><code>http:\/\/api.wipmania.com\/[DIRECCION_IP]?[URL]<\/code><\/p>\n<p>donde <code>[DIRECCION_IP]<\/code> es la IP de la que queremos obtener el pa\u00eds y <code>[URL]<\/code> es la direcci\u00f3n de nuestra p\u00e1gina web. <\/p>\n<p>La \u00fanica pega que tiene este magn\u00edfico servicio es que limitan el n\u00famero de consultas que se pueden realizar por dominio y d\u00eda a 10.000 (para eso hace falta el par\u00e1metro URL). Si prevemos que nuestro website puede generar m\u00e1s de 10.000 consultas diarias, entonces esta soluci\u00f3n no es v\u00e1lida, o habr\u00eda que combinarla con alg\u00fan tipo de limitaci\u00f3n interna que previera un comportamiento por defecto una vez rebasado el l\u00edmite diario.<\/p>\n<p>Investigando m\u00e1s a fondo descubr\u00ed que el API de wipmania.com <strong>tambi\u00e9n contaba con una interfaz de consulta javascript-json<\/strong> y -mira qu\u00e9 bien- si la consulta se hac\u00eda a trav\u00e9s de este API en vez de a trav\u00e9s del m\u00e9todo GET anteriormente descrito, <strong>la limitaci\u00f3n de consultas por d\u00eda desaparec\u00eda<\/strong>, por lo tanto esta fue la soluci\u00f3n inicial para afterguantanamo.com: al cargar la p\u00e1gina principal se ejecutaba  un script que realizaba la consulta por ajax (con jQuery para facilitar las cosas) hacia wipmania.com y realizaba una redirecci\u00f3n una vez averiguado el c\u00f3digo de la ciudad. El script era algo as\u00ed:<\/p>\n<pre class=\"prettyprint\">$(document).ready(function(){\r\n  var castellano = \"AR,BO,CL,...\"; \/\/pa\u00edses de habla castellana\r\n  var frances = \"FR,CD,...\"; \/\/pa\u00edses de habla francesa\r\n  var italiano = \"IT,VA,...\"; \/\/pa\u00edses de habla italiana\r\n  $.getJSON(\"http:\/\/api.wipmania.com\/jsonp?callback=?\", function(data) {\r\n    if(castellano.indexOf(data.address.country_code)>-1)\r\n      location.href=\"castellano\/\";\r\n    else if(frances.indexOf(data.address.country_code)>-1)\r\n      location.href=\"francais\/\";\r\n    else if(italiano.indexOf(data.address.country_code)>-1)\r\n      location.href=\"italiano\/\";\r\n    else location.href=\"english\/\";\r\n  });\r\n})<\/pre>\n<p>Para completar la informaci\u00f3n he de decir que el API javascript-json devuelve muchos m\u00e1s datos aparte del c\u00f3digo del pa\u00eds: latitude, longitude, zoom, address.city, address.country, address.country_code y address.region. Se puede encontrar una explicaci\u00f3n m\u00e1s detallada de lo que significa cada uno de estos resultados aqu\u00ed : <a href=\"http:\/\/www.wipmania.com\/en\/blog\/geolocation-api-json-jsonp\/\">http:\/\/www.wipmania.com\/en\/blog\/geolocation-api-json-jsonp\/<\/a>, y por cierto tambi\u00e9n se puede descargar un listado de todos los c\u00f3digos de todos los pa\u00edses aqu\u00ed : <a href=\"http:\/\/static.wipmania.com\/static\/countries.txt\">http:\/\/static.wipmania.com\/static\/countries.txt<\/a>.<\/p>\n<p><strong>Esta soluci\u00f3n funciona perfectamente excepto por un peque\u00f1o detalle : la latencia o retardo que sufre la p\u00e1gina como consecuencia de la consulta hacia un servicio externo<\/strong>, que en caso de wipmania.com es muy bajo, pero aun as\u00ed, son 2 \u00f3 3 segundos que se a\u00f1aden a la carga inicial de la p\u00e1gina, y yo quer\u00eda que esta fuera lo m\u00e1s r\u00e1pida posible.<\/p>\n<p><strong>GeoIP de MaxMind al rescate<\/strong><\/p>\n<p>A pesar de que la p\u00e1gina funcionaba correctamente y que despu\u00e9s de varias semanas de prueba no nos hab\u00eda dado ning\u00fan problema, yo no estaba contento con esos segundos de m\u00e1s que se a\u00f1ad\u00edan siempre a la carga inicial de la p\u00e1gina. La soluci\u00f3n para ello era conseguir de alguna forma consultar alg\u00fan tipo de base de datos local que a ser posible devolviera lo mismo que Wipmania: un c\u00f3digo de 2 letras que me permitiese identificar los pa\u00edses f\u00e1cilmente, y obviamente yo no estaba por la labor de crear semejante tipo de base de datos.<\/p>\n<p>La b\u00fasqueda me llev\u00f3 al sistema propuesto por <a href=\"http:\/\/www.maxmind.com\">Maxmind<\/a> que es precisamente eso: una base de datos local que te puedes descargar e instalar en tu servidor y que adem\u00e1s tiene APIs para un mont\u00f3n de lenguajes (C, Perl, PHP, Java, Python, C#, Ruby, VB.NET, Pascal, etc). <strong>En este caso la soluci\u00f3n tambi\u00e9n es gratuita si te conformas con pocas prestaciones<\/strong> (obtener informaci\u00f3n s\u00f3lo acerca del pa\u00eds y bas\u00e1ndose en una BD con actualizaci\u00f3n semi-frecuente) y de pago si se desean m\u00e1s prestaciones (informaci\u00f3n sobre ciudades e incluso poblaciones, o actualizaci\u00f3n de la BD permanente). Mi caso estaba claro: la base de datos gratuita me bastaba y me sobraba y con el API PHP la soluci\u00f3n era perfecta.<\/p>\n<p>La instalaci\u00f3n pasa s\u00f3lo por la descarga y guardado en cualquier carpeta accesible por nuestros scripts PHP del \u00fanico fichero que compone la BD de pa\u00edses y en mi caso la descarga del API PHP \u201cgeoip.inc.php\u201d. Una vez instalado, s\u00f3lo me hizo falta a\u00f1adir el siguiente c\u00f3digo PHP en la p\u00e1gina de inicio:<\/p>\n<pre class=\"prettyprint\">\r\ninclude(\"geoip.inc.php\");\r\n$gi = geoip_open(\"[ruta_hacia]\/geoip.dat\",GEOIP_STANDARD);\r\n$codigo_pais = geoip_country_code_by_addr($gi,$_SERVER[\"REMOTE_ADDR\"]);\r\necho \"...\" . $codigo_pais . \"...\" \/\/meterlo en cualquier contenedor visible por javascript\r\n<\/pre>\n<p>y posteriormente s\u00f3lo hace falta modificar el javascript original para que en vez de tomar el c\u00f3digo de wipmania lo tome del contenedor en el que hemos escrito nuestro c\u00f3digo sacado de la BD local. El c\u00f3digo javascript modificado quedar\u00eda algo as\u00ed:<\/p>\n<pre class=\"prettyprint\">$(document).ready(function(){\r\n  var castellano = \"AR,BO,CL,...\"; \/\/pa\u00edses de habla castellana\r\n  var frances = \"FR,CD,...\"; \/\/pa\u00edses de habla francesa\r\n  var italiano = \"IT,VA,...\"; \/\/pa\u00edses de habla italiana\r\n  var codigo_pais = $(\"[acceso_al_contenedor]\").val();\r\n  if(castellano.indexOf(codigo_pais)>-1)\r\n    location.href=\"castellano\/\";\r\n  else if(frances.indexOf(codigo_pais)>-1) \r\n    location.href=\"francais\/\";\r\n  else if(italiano.indexOf(codigo_pais)>-1)\r\n    location.href=\"italiano\/\";\r\n  else location.href=\"english\/\";\r\n})<\/pre>\n<p>Ni qu\u00e9 decir que la latencia por consulta externa queda eliminada y que la velocidad de carga de la p\u00e1gina ahora s\u00f3lo depende de la velocidad y carga del propio servidor web. Misi\u00f3n cumplida.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hace poco estuve trabajando en la web afterguantanamo.com y uno de los requisitos que quer\u00edamos cubrir era la posibilidad de tener la web en varios idiomas y que en funci\u00f3n del pa\u00eds desde el que se visitase (despu\u00e9s de todo se trata de un tema internacional), la web se mostrase en un idioma o en otro de manera autom\u00e1tica. Para conseguirlo era necesario utilizar alg\u00fan sistema de geoposicionamiento, por lo que me puse a investigar las opciones disponibles. Despu\u00e9s de mirar por aqu\u00ed y por all\u00e1, encontr\u00e9 que el servicio de wipmania.com era una soluci\u00f3n r\u00e1pida bastante f\u00e1cil de implementar que no exig\u00eda pr\u00e1cticamente ning\u00fan esfuerzo. Adem\u00e1s, el servicio es gratuito, lo que lo hizo una elecci\u00f3n muy sencilla respecto a otras soluciones de pago. Para utilizar este servicio no hay m\u00e1s que pasar a su servidor la consulta con la IP de la que queremos averiguar el pa\u00eds, y [&hellip;]<\/p>\n<p><a class=\"more-link\" href=\"https:\/\/capri.dev\/blog\/opciones-disponibles-para-aplicaciones-web-que-necesitan-geoposicionamiento\/\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[83,84,85],"class_list":["post-125","post","type-post","status-publish","format-standard","hentry","category-tecnico","tag-geoposicionamiento","tag-maxmind","tag-wipmania"],"_links":{"self":[{"href":"https:\/\/capri.dev\/blog\/wp-json\/wp\/v2\/posts\/125","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/capri.dev\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/capri.dev\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/capri.dev\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/capri.dev\/blog\/wp-json\/wp\/v2\/comments?post=125"}],"version-history":[{"count":0,"href":"https:\/\/capri.dev\/blog\/wp-json\/wp\/v2\/posts\/125\/revisions"}],"wp:attachment":[{"href":"https:\/\/capri.dev\/blog\/wp-json\/wp\/v2\/media?parent=125"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/capri.dev\/blog\/wp-json\/wp\/v2\/categories?post=125"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/capri.dev\/blog\/wp-json\/wp\/v2\/tags?post=125"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}