Proxy-handler for graphhopper.com.
Today all maps and routing online services for site owners is been not free. GraphHopper is a good worldwide paid service for showing routing in map, but the paid key has been transfer through internet and showing in browser for client in unmasked clear form. In other side this service has limit for day's and month's request.
For solve problem to hide the key I found a one way - to create a server's proxy-hadler. I had learning a structure of graphhopper internal javascript library and found some interesting modules. Firstly, graphhopper_api_distance.js contains key in clear form, that I have replaced to masked key.
43: var host, defaultKey = "55555555-5555-5555-5555-555555555555",
44: profile = "car",
45: ghRouting = new GraphHopper.Routing({
46: key: defaultKey,
47: host: host,
48: vehicle: profile,
49: locale: "ru",
50: elevation: !1
51: }),
52: routingMap = createMap("place-map"),
53: routingLayer = L.geoJson().addTo(routingMap);
And after details learning of graphhopper_api.js module I had understanding so this module contains six prototypes of javascript objects with definition of direct URI request to graphopper server, like below. And after that I replace request for graphhopper.com to myowndomain.com
4471: 17: [function (k, v, x) {
4472: var e = k("superagent"),
4473: u = k("bluebird"),
4474: q = new(k("./GHUtil"));
4475: GraphHopperRouting = function (a) {
4476: this.points = [];
4477: this.host = "https://myowndomain.com/graphhopperproxy/graphhopperproxy.ashx"; // https://graphhopper.com/api/1
4478: this.vehicle = "car";
4479: this.debug = !1;
4480: this.data_type = "application/json";
4481: this.locale = "en";
4482: this.instructions = this.points_encoded = !0;
4483: this.elevation = !1;
4484: this.optimize = "false";
4485: this.basePath = "/route";
4486: this.timeout = 1E4;
4487: this.graphhopper_maps_host =
4488: "https://graphhopper.com/maps/?";
4489: this.turn_sign_map = {
4490: "-6": "leave roundabout",
4491: "-3": "turn sharp left",
4492: "-2": "turn left",
4493: "-1": "turn slight left",
4494: 0: "continue",
4495: 1: "turn slight right",
4496: 2: "turn right",
4497: 3: "turn sharp right",
4498: 4: "finish",
4499: 5: "reached via point",
4500: 6: "enter roundabout"
4501: };
4502: q.copyProperties(a, this)
4503: };
This handler store response of graphopper.com to DB and send it to client.
After that I had created a virtual directory in IIS and convert it to application. In this directory I have placed all code of my proxy handler.
Also I had created database with clear and masked user keys and had provided access for this DB with full security compliance.
After above points was done I had created simple ASP.NET project with linq-to-sql ORM and extremaly simply code.
1: <%@ WebHandler Language="VB" Class="GraphhopperProxy" %>
2:
3: Imports System
4: Imports System.Web
5:
6: Public Class GraphhopperProxy : Implements IHttpHandler
7:
8: Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
9: Dim GrDB As New GraphhopperDBDataContext
10:
11: Dim RawUrl As String = context.Server.HtmlDecode(context.Request.RawUrl)
12: If context.Request.Headers("referer").ToLower.Contains("votpusk.ru") And _
13: context.Request.Headers("host").ToLower.Contains("votpusk.ru") And _
14: context.Request.UrlReferrer.ToString.ToLower.Contains("votpusk.ru") Then
15:
16: GrDB.RequestTests.InsertOnSubmit(New RequestTest With {.[date] = Now, .type = "RawURL", .txt = context.Request.RawUrl})
17:
18: Dim Keys = GrDB.GraphhoperKeys.ToList
19: For Each Row In Keys
20: RawUrl = RawUrl.Replace(Row.MaskedKey.ToString, Row.RealKey.ToString)
21: Next
22:
23: Dim RequestURL As String = RawUrl.Replace("/graphhopperproxy/graphhopperproxy.ashx", "https://graphhopper.com/api/1")
24: GrDB.RequestTests.InsertOnSubmit(New RequestTest With {.[date] = Now, .type = "RequestURL", .txt = RequestURL})
25:
26: Dim Html As String = GetPage(RequestURL, System.Text.Encoding.UTF8)
27: GrDB.RequestTests.InsertOnSubmit(New RequestTest With {.[date] = Now, .type = "Response", .txt = Html})
28: GrDB.SubmitChanges()
29:
30: context.Response.ContentType = "application/json;charset=utf-8"
31: context.Response.ContentEncoding = UTF8Encoding.UTF8
32: context.Response.Write(Html)
33: Else
34: context.Response.Write("forbidden")
35: End If
36: End Sub
37:
38: Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
39: Get
40: Return False
41: End Get
42: End Property
43:
44:
45: Public Shared Function GetPage(ByVal URL As String, Encoding As System.Text.Encoding) As String
46: Try
47: '???????????? ???? HTTP
48: Dim PageRequest As System.Net.HttpWebRequest = CType(System.Net.WebRequest.Create(URL), System.Net.HttpWebRequest)
49: PageRequest.Headers("Origin") = "https://routes.votpusk.ru"
50: PageRequest.Headers("TE") = "Trailers"
51: PageRequest.Accept = "application/json"
52: PageRequest.ContentType = "application/json"
53: PageRequest.Method = "GET"
54: '?????????????????? ????????????
55: Dim PageResponse As System.Net.HttpWebResponse = PageRequest.GetResponse
56: '?????????????? ??????????
57: Dim Reader As New System.IO.StreamReader(PageResponse.GetResponseStream(), Encoding, True)
58: Dim HTML As String = Reader.ReadToEnd
59: Reader.Close()
60: '?????????????????? ?? ????????????
61: Return HTML
62: Catch ex As Exception
63: Return "Error: " & ex.Message
64: End Try
65: End Function
66:
67:
68: End Class
I won't describe all of this project, this is only point for quick start, but further this project has many extension, like cache response of graphhopper and autonomy working without request to graphopper.
|