Zacząłem, jak sądzę, będąc dzieckiem, szukając sposobów na hostowanie publicznego serwera z lokalnego serwera w NPM . Szukano takich słów kluczowych jak:
- Odwrotny serwer proxy
- Tunel Ws
- Odwrotny HTTP
- Tunel TCP
Próbowałem ws-tunelu:
Potrzebny był osobny port do połączenia WebSocket i osobny port do hostowania serwera WWW . Mimo że w ten sposób mogło to działać, Heroku zezwoliło na użycie tylko 1 portu , a ja nie wiedziałem, czy jakikolwiek inny dostawca chmury zezwoliłby na 2 porty publiczne (czułem, że nie jest to możliwe).
Próbowałem reverse-http:
Może działać jako klient Reverse HTTP . Odwrotny HTTP to protokół dostarczany przez IETF. Ale potem potrzebowałem odwrotnego serwera HTTP . Jednak nadal występował problem ze zwrotnym HTTP , ponieważ mógł on przesyłać strumieniowo tylko jedno żądanie na raz . Było to w zasadzie połączenie HTTP w odwrotnej kolejności od serwera publicznego do lokalnego . Oznaczało to, że albo musiałbym w jakiś sposób serializować żądania wielu użytkowników do jednego lub wielu połączeń (wiele odwrotnych połączeń HTTP musiałoby zostać skonfigurowanych między serwerem lokalnym a serwerem publicznym ).
Spróbuj użyć pakietów TCP:
Wtedy zdałem sobie sprawę, że można to zrobić za pomocą jednego połączenia i prostszej niebuforowanej metody proxy. Odwrotny HTTP może wymagać buforowania, jeśli pojawiło się nowe połączenie i wszystkie połączenia odwrotnego HTTP były w użyciu. Rozważ użycie prostych pakietów o następującym formacie:
--------------------------------------
| Packet Size | Connection ID | Data |
--------------------------------------
Szukałem sposobu, aby to zrobić za pomocą WebSockets, jeśli miałyby jakąś istniejącą funkcję, której mógłbym użyć, ale wtedy zobaczyłem, że Heroku zezwala na dowolną aktualizację HTTP, więc zdecydowałem się na aktualizację TCP. Wiem, wymyśliłem to. Oto jak wygląda nagłówek, sprawdziłem, czy Heroku go akceptuje:
GET / HTTP/1.1
Upgrade: tcp
Connection: Upgrade
Origin: XXX
Ok, teraz pojawił się pomysł, jak zaktualizować połączenie między serwerem lokalnym a serwerem publicznym za pomocą protokołu TCP, a następnie komunikować się za pomocą pakietów. Nadal jednak format pakietu nie mówi nam, czy użytkownik się połączył, czy rozłączył. Mówi nam tylko, jakie dane użytkownik wysłał. Więc dodałem kolejne pole do pakietu:
----------------------------------------------
| Packet Size | Event | Connection ID | Data |
----------------------------------------------
Jednym z nierozwiązanych jeszcze problemów było rozróżnienie połączenia między użytkownikiem a serwerem lokalnym, ponieważ korzystamy z tego samego portu dla obu z nich. Można to zrobić na wiele sposobów, ale zdecydowałem się na konkretny User-Agent
serwer lokalny.
Więcej wątpliwości, czy zbudować kod serwera publicznego za pomocą HTTP Node czy TCP Node. Tym razem czytałem o kodowaniu fragmentarycznym, zwiastunach i zdecydowałem, że lepiej będzie użyć TCP. Tak więc musiałbym przeanalizować początkowe żądanie połączenia i na podstawie określonego typu przetworzyć je jako użytkownik lub serwer lokalny. Ale wyobrażałem sobie, że wystąpi problem z wydajnością, ponieważ analizowałbym nagłówki HTTP każdego połączenia. Ale jeśli użyjemy rzadkiej metody HTTP do szybkiego rozróżnienia, na przykład HEAD
, musielibyśmy odczytać tylko 4 znaki. Możemy więc teraz to zrobić:
1. If first 4 characters not HEAD, process as User.
2. Parse all the HTTP headers.
3. If User-Agent is special value, process as Local server
4. Process as User.
Dodałem także obsługę wielu kanałów, które mogą teraz umożliwić mi dostęp jako serwer SSH działający na innym komputerze (prywatny adres IP). Przeniesiłem kod i ozdobiłem README: https://github.com/nodef/rhost .
Kilka interesujących stron, które znalazłem podczas wyszukiwania: