Existem várias maneiras baratas de hospedar um site estático gerado com um gerador de site estático como Jekyll, Hugo ou Pelican: Todo este blog é gerado estaticamente usando Jekyll. No entanto, não posso usar nenhuma das opções acima porque, ao longo da existência deste blog, mudei nomes de domínio, mudei esquemas de URL e renomeei posts, e quero mantenha vivas todas as URLs antigas Tenho hospedado este blog usando Apache e, mais recentemente, nginx em uma única máquina virtual, e os recursos de redirecionamento de qualquer um dos softwares funcionam muito bem, mas eu estava pronto para hospedá-lo em algum lugar novo e diferente Uma postagem anterior descreve como redireciono URLs de um domínio antigo para um novo domínio usando o Google App Engine e Python, mas agora eu precisava de uma maneira de fornecer conteúdo estático **e** URLs de redirecionamento do mesmo domínio. Esse mesmo requisito de redirecionamento de domínio é o motivo pelo qual não posso simplesmente usar o recurso somente de conteúdo estático do Google App Engine (link na lista acima). No entanto, posso usar o Google App Engine em combinação com um aplicativo Golang simples para fornecer conteúdo estático **e** redirecionamentos do mesmo domínio ## Por que o Google App Engine? Antes de mergulhar no restante da postagem, talvez você esteja se perguntando: por que hospedar um blog no Google App Engine? Aqui estão meus motivos: - Se o seu tráfego se encaixa no nível gratuito do App Engine de 28 horas de instância e 1 GB de tráfego de saída por dia, a hospedagem do blog é praticamente gratuita - O envio de atualizações é feito com um comando - O registro e o monitoramento são integrados usando o Stackdriver - Escala automática para cima e para baixo com base nos padrões de tráfego - Com alguns cliques, os logs da web podem ser facilmente enviados para algo como o BigQuery para armazenamento de longo prazo e análise ad hoc - Certificados SSL gerenciados usando o Letâ¢ÃÂÃÂs Encrypt ## Pré-requisitos Esta postagem pressupõe o seguinte: - Você está familiarizado com o Google Cloud Platform (GCP) e já criou um projeto GCP - Você instalou o Google Cloud SDK - Você autenticou o gcloudcommand contra sua Conta do Google Criar um projeto do GCP Se você ainda não criou um ** Projeto GCP siga estas etapas: - Abra um navegador da Web e crie ou faça login em uma Conta do Google - Navegue até o Console do GCP - Se este for seu primeiro projeto GCP, você será solicitado a criar um projeto GCP. Cada Conta do Google recebe US$ 300 em crédito para usar em 12 meses no GCP. Você é obrigado a inserir um cartão de crédito para criar um projeto GCP, mas não será cobrado até que o crédito de $ 300 seja consumido ou 12 meses expirem - Se este for um novo projeto do GCP, você precisará ativar a API do Compute Engine navegando até a seção Compute Engine do console do GCP e aguardar a conclusão da inicialização Instale o SDK do Google Cloud Se você ainda não instalou o ** Google Cloud SDK siga as instruções aqui Autenticar gcloud Depois de criar um projeto do GCP e instalar o Google Cloud SDK, a última etapa é autenticar o comando gcloud para sua Conta do Google. Abra seu aplicativo de terminal e execute o seguinte comando: gcloud login de autenticação Uma página da web será aberta em seu navegador. Selecione sua Conta do Google e dê permissão para acessar o GCP. Depois de concluído, você será autenticado e pronto para seguir em frente ## Crie um diretório Em seguida, crie um diretório em algum lugar de sua estação de trabalho para armazenar seu aplicativo do Google App Engine: mkdir ~/Sites/example.com/app_engine Mude para esse diretório: cd ~/Sites/example.com/app_engine O restante desta postagem assumirá que você está trabalhando dentro deste diretório Além disso, crie um diretório dentro do diretório **app_engine** chamado **estático mkdir ~/Sites/example.com/app_engine/static Você revisitará este diretório mais tarde ## Criar app.yaml O Google App Engine geralmente requer dois arquivos: **app.yaml** e um **arquivo de aplicativo** escrito em Python, Golang, Java ou PHP - neste caso, será Golang. **app.yaml** fornece a configuração necessária para executar seu aplicativo. Há muitos parâmetros diferentes que podem existir em **app.yaml Esses parâmetros podem diferir com base na linguagem de programação usada. Para esta postagem, o Golang será usado e você pode encontrar todos os parâmetros disponíveis do Golang aqui Criar arquivo **app.yaml** com o seguinte conteúdo: tempo de execução: go api_version: go1 manipuladores: - url:script: _go_app seguro: sempre redirecionar_http_response_code: 301 Notar que **seguro: sempre** foi definido. Isso significa que o aplicativo Golang sempre será servido por HTTPS. Se um usuário final navegar para o aplicativo da web por HTTP, ele será, por padrão, redirecionado 302 para a versão HTTPS. É por isso que **redirect_http_response_code: 301** também foi definido. Sempre desejo que o aplicativo da Web seja servido por HTTPS e não quero que os mecanismos de pesquisa interpretem o redirecionamento de HTTP para HTTPS como um redirecionamento temporário; é um redirecionamento permanente Se você tiver recursos estáticos, e provavelmente tem, é uma prática recomendada informar o App Engine sobre isso e permitir que ele exiba esses recursos do armazenamento de objetos em vez de seu aplicativo. Fazer isso é fácil e também é feito através do Arquivo **app.yaml** Por exemplo, se você tiver um arquivo favicon, um diretório CSS, um diretório Javascript e um diretório de imagens, use o seguinte Arquivo **app.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 seguro: sempre redirecionar_http_response_code: 301 ## Criar main.go Em seguida, você precisa do arquivo de aplicativo Golang Para que o código a seguir atenda às suas necessidades, crie o arquivo **main.go copie e cole o código abaixo, e faça as seguintes modificações: - No variável de domínio, altere o valor para corresponder ao seu nome de domínio com o protocolo HTTP correto - No urlsmap, substitua todos os pares de valores-chave para corresponder aos redirecionamentos necessários. Substitua cada chave apenas pela parte do caminho ( /example-post-1.html em vez de httpsexample.com/example-post-1.html) do URL antigo do domínio atual que você deseja mantenha vivo. Em seguida, substitua cada valor pela parte do caminho do novo URL do domínio atual para o qual você deseja redirecionar Todos os redirecionamentos serão redirecionamentos 301. Isso pode ser modificado alterando **301** no código abaixo para um código de status de redirecionamento HTTP diferente, como **302** package main import ( "net/http""os""strings") func init() { http.HandleFunc handler) } func handler(w http.ResponseWriter, r *http.Request) { // Verdadeiro (ok) se solicitado path está no mapa de urls if value, ok := urls[r.URL.Path]; ok { value = domínio + value http.Redirect(w, r, value, 301) } else { path := "static/"+ r.URL.Path // Retorna 403 se a requisição HTTP for para um diretório que existe e não não contém um arquivo index.html if f, err := os.Stat(path); err == nil&& f.IsDir() { index := strings.TrimSuffix(path,+ "/index.html"if _, err := os.Open(index); err != nil { w.WriteHeader (403) w.Writebytehtml> 403 Proibido

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