Istnieje kilka niedrogich sposobów hostowania statycznej witryny internetowej generowanej za pomocą generatora witryn statycznych, takiego jak Jekyll, Hugo lub Pelican: Cały ten blog jest generowany statycznie przy użyciu Jekyll. Nie mogę jednak skorzystać z żadnej z powyższych opcji, ponieważ przez cały okres istnienia tego bloga zmieniałem nazwy domen, schematy adresów URL i nazwy postów, a chcę zachować przy życiu wszystkie stare adresy URL Hostowałem tego bloga za pomocą Apache, a ostatnio nginx na jednej maszynie wirtualnej, a funkcje przekierowania obu programów działają dobrze, ale byłem gotowy, aby hostować go w nowym i innym miejscu W poprzednim poście opisano, jak przekierowuję adresy URL ze starej domeny do nowej za pomocą Google App Engine i Pythona, ale teraz potrzebowałem sposobu na wyświetlanie treści statycznych **i** przekierowują adresy URL z tej samej domeny. To samo wymaganie przekierowania domeny jest powodem, dla którego nie mogę po prostu użyć funkcji tylko statycznej zawartości Google App Engine (link na powyższej liście). Mogę jednak używać Google App Engine w połączeniu z prostą aplikacją Golang do obsługi zarówno treści statycznych **, jak ** tych samych przekierowań domen ## Dlaczego Google App Engine? Zanim przejdziesz do dalszej części posta, być może zastanawiasz się, po co prowadzić bloga w Google App Engine? Oto moje powody: - Jeśli Twój ruch mieści się w ramach bezpłatnego poziomu App Engine wynoszącego 28 godzin instancji i 1 GB ruchu wychodzącego dziennie, hosting bloga jest praktycznie bezpłatny - Wypychanie aktualizacji odbywa się za pomocą jednego polecenia - Rejestrowanie i monitorowanie są zintegrowane za pomocą Stackdriver - Automatyczne skalowanie w górę iw dół na podstawie wzorców ruchu - Za pomocą kilku kliknięć dzienniki sieciowe można łatwo przesłać do czegoś takiego jak BigQuery w celu długoterminowego przechowywania i analizy ad hoc - Zarządzane certyfikaty SSL przy użyciu LetâÃÂÃÂs Encrypt ## Wymagania wstępne Ten post zakłada, że: - Znasz Google Cloud Platform (GCP) i masz już utworzony projekt GCP - Zainstalowałeś Google Cloud SDK - Uwierzytelniłeś gcloudcommand na swoim koncie Google Utwórz projekt GCP Jeśli jeszcze nie utworzyłeś **Projekt GCP wykonaj następujące kroki: - Otwórz przeglądarkę internetową i utwórz konto Google lub zaloguj się na nie - Przejdź do konsoli GCP — Jeśli jest to Twój pierwszy projekt GCP, zostaniesz poproszony o utworzenie projektu GCP. Każde konto Google otrzymuje kredyt w wysokości 300 USD do wykorzystania w ciągu 12 miesięcy na rzecz GCP. Aby utworzyć projekt GCP, musisz podać dane karty kredytowej, ale opłata nie zostanie naliczona do momentu wykorzystania kredytu w wysokości 300 USD lub upłynięcia 12 miesięcy – Jeśli jest to nowy projekt GCP, musisz włączyć interfejs API Compute Engine, przechodząc do sekcji Compute Engine w konsoli GCP i zaczekaj na zakończenie inicjalizacji Zainstaluj pakiet Google Cloud SDK Jeśli jeszcze nie zainstalowałeś **Google Cloud SDK postępuj zgodnie z instrukcjami tutaj Uwierzytelnij gcloud Ostatnim krokiem po utworzeniu projektu GCP i zainstalowaniu pakietu SDK Google Cloud jest uwierzytelnienie gcloud na swoje konto Google. Otwórz aplikację terminalową i uruchom następujące polecenie: logowanie z autoryzacją gcloud W przeglądarce internetowej otworzy się strona internetowa. Wybierz swoje konto Google i nadaj mu uprawnienia dostępu do GCP. Po zakończeniu zostaniesz uwierzytelniony i będziesz gotowy, aby przejść dalej ## Utwórz katalog Następnie utwórz katalog gdzieś na swojej stacji roboczej, aby przechowywać aplikację Google App Engine: mkdir ~/Sites/example.com/app_engine Przejdź do tego katalogu: cd ~/Sites/example.com/app_engine Pozostała część tego wpisu zakłada, że ​​pracujesz w tym katalogu Dodatkowo utwórz katalog wewnątrz pliku **app_engine** katalog o nazwie **static mkdir ~/Sites/example.com/app_engine/static Później ponownie odwiedzisz ten katalog ## Utwórz plik app.yaml Google App Engine zwykle wymaga dwóch plików: **app.yaml** i **plik aplikacji** napisany w Pythonie, Golangu, Javie lub PHP – w tym przypadku będzie to Golang. **app.yaml** zapewnia konfigurację niezbędną do uruchomienia aplikacji. Istnieje wiele różnych parametrów, które mogą istnieć w **app.yaml Parametry te mogą się różnić w zależności od używanego języka programowania. W tym poście zostanie użyty Golang, a wszystkie dostępne parametry Golanga znajdziesz tutaj Utwórz plik **app.yaml** o następującej zawartości: środowisko wykonawcze: go api_version: go1 handlers: - url:script: _go_app bezpieczne: zawsze redirect_http_response_code: 301 Zauważ, że **bezpieczne: zawsze** zostało ustawione. Oznacza to, że aplikacja Golang będzie zawsze obsługiwana przez HTTPS. Jeśli użytkownik końcowy przejdzie do aplikacji internetowej przez HTTP, zostanie domyślnie przekierowany 302 do wersji HTTPS. Dlatego też ustawiono **redirect_http_response_code: 301**. Zawsze chcę, aby aplikacja internetowa była obsługiwana przez HTTPS i nie chcę, aby wyszukiwarki interpretowały przekierowanie z HTTP na HTTPS jako tymczasowe przekierowanie; jest to stałe przekierowanie Jeśli masz zasoby statyczne, a prawdopodobnie tak jest, najlepiej jest poinformować o tym App Engine i pozwolić, by udostępniał te zasoby z obiektowej pamięci masowej zamiast z aplikacji. Robienie tego jest łatwe i odbywa się również za pomocą **plik aplikacji.yaml** Na przykład, jeśli masz plik favicon, katalog CSS, katalog JavaScript i katalog obrazów, użyj następującego **plik aplikacji.yaml**: runtime: go api_version: go1 handlers: - url: /favicon.png$ static_files: static/favicon.png upload: static/favicon.png - url: /css static_dir: static/css - url: /js static_dir: static/js - url: /images static_dir: static/images - url: script: _go_app security: always redirect_http_response_code: 301 ## Utwórz main.go Następnie potrzebujesz pliku aplikacji Golang Aby poniższy kod spełniał Twoje potrzeby, utwórz plik **main.go skopiuj i wklej poniższy kod i wprowadź następujące modyfikacje: - W domainvariable, zmień wartość, aby dopasować nazwę domeny do prawidłowego protokołu HTTP - W urlsmap, zastąp wszystkie pary klucz-wartość, aby pasowały do ​​potrzebnych przekierowań. Zastąp każdy klucz tylko fragmentem ścieżki ( /example-post-1.htmlzamiast httpsexample.com/example-post-1.html) starego adresu URL bieżącej domeny, do którego chcesz utrzymać przy życiu. Następnie zastąp każdą wartość fragmentem ścieżki bieżącego adresu URL domeny, na który chcesz przekierować Wszystkie przekierowania będą przekierowaniami 301. Można to zmienić, zmieniając **301** w poniższym kodzie do innego kodu stanu przekierowania HTTP, takiego jak **302** pakiet main import ("net/http""os""strings") func init() { http.HandleFunc handler) } func handler(w http.ResponseWriter, r *http.Request) { // True (ok) if request ścieżka znajduje się na mapie adresów URL, jeśli wartość, ok := urls[r.URL.Path]; ok { wartość = domena + wartość http.Redirect(w, r, wartość, 301) } else { ścieżka := "static/"+ r.URL.Path // Zwróć 403, jeśli żądanie HTTP dotyczy katalogu, który istnieje i nie nie zawiera pliku index.html jeśli f, err := os.Stat(ścieżka); err == nil&& f.IsDir() { index := strings.TrimSuffix(ścieżka,+ "/index.html"if _, err := os.Open(index); err != nil { w.WriteHeader (403) w.Writebytehtml> 403 Zabronione

403 Forbidden

return } } // Return custom 404 page if HTTP request is to a non-existent file if _, err := os.Stat(path); os.IsNotExist(err) { w.WriteHeader(404) http.ServeFile(w, r, "static/404.html") return // Withoutreturn, a "404 page not found" string will be displayed at the bottom of your custom 404 page } http.ServeFile(w, r, path) return } } var domain string = "httpsexample.com" var urls = map[string]string{ "/example-post-1.html": "/post/example-post-1.html", "/example-post-2.html": "/post/example-post-2.html", "/example-post-3.html": "/post/example-post-3.html", } ## Generate the Static Content With **app.yaml** and **main.go** saved, the last piece is to generate your static content and store it in the **static** directory you created earlier How you do this entirely depends on what static site generator you are using If you are using Jekyll, you can configure the **destination** parameter in Jekyll’s _ **config.yml** file to save your static content in any directory on your workstation. So, you could set the **destination** parameter to Sites/example.com/app_engine/static and, every time you run jekyll build, the static content will be saved in that directory ## Deploy to App Engine With **app.yaml **main.go and your static content generated, you are ready to deploy your Google App Engine application Assuming gcloud is already pointed at the Google Cloud Project you want to deploy to, verify with gcloud config list project, run the following command: gcloud app deploy The command will output the appspot URL your application will be deployed to and ask if you want to continue. Typically, the appspot URL is **httpsyour-project-id.appspot.com This is also a useful self-check to make sure you are not deploying your application to the wrong Google Cloud Project. If everything looks okay, type **Y** and **Enter** to deploy your application. Depending on how large your static content is, your application should be deployed within about one minute ## Setup DNS At this point, your application is deployed under URL **httpsyour-project-id.appspot.com Unless your website uses that as its domain name, you will probably want to setup a custom domain that uses your actual current domain name The App Engine section of the Google Cloud Console can be used to do this. Go here and follow the instructions to configure your custom domain Once that is complete and DNS has had time to propagate, you should be able to navigate in your web browser to one of your current domain’s old URLs, for example **httpsexample.com/example-post-1.html and have it redirect to your current domain’s new URLs, for example **httpsexample.com/post/example-post-1.html** ## Pushing Updates To push updates, make the necessary changes in your static site’s source directory, regenerate the static content, and redeploy to Google App Engine by changing into the Sites/example.com/app_engine** directory and running gcloud app deploy ## References - A Surprising Feature of Golang that Colored Me Impressed - How to check if a map contains a key in go? - Disable directory listing with http.FileServer - 3 Ways to Disable http.FileServer Directory Listings - Handling HTTP Request Errors in GO - HTTP and Error management in Go - please add ability to set custom 404 notFoundHandler for http.FileServer