Appengine - Deployment of hidden folder
For anyone else coming here like me after trying to serve the challenge for letsencrypt in a static manner in Google App Engine and failing, the following did it for me: (one might be able to actually do it statically, but I didn't try it as I didn't want to spend more time trying out stuff and Ian apparently tried that and could not make it work [maybe the copy command done internally on Google App Engine ignores the directories that start with a dot] )
Taken from http://igorartamonov.com/2015/12/lets-encrypt-ssl-google-appengine/ credits go to Igor Artamonov.
Just build a servlet like:
public class LetsencryptServlet extends HttpServlet {
public static final Map<String, String> challenges = new HashMap<String, String>();
static {
challenges.put("RzrvZ9gd7EH3i_TsJM-B0vdEMslD4oo_lwsagGskp6c",
"RzrvZ9gd7EH3i_TsJM-B0vdEMslD4oo_lwsagGskp6c.ONrZa3UelibSWEX270nTUiRZKPFXw096nENWbMGw0-E");
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
if (!req.getRequestURI().startsWith("/.well-known/acme-challenge/")) {
resp.sendError(404);
return;
}
String id = req.getRequestURI().substring("/.well-known/acme-challenge/".length());
if (!challenges.containsKey(id)) {
resp.sendError(404);
return;
}
resp.setContentType("text/plain");
resp.getOutputStream().print(challenges.get(id));
}
}
And add to web.xml
somethine like:
<servlet>
<servlet-name>letsencrypt</servlet-name>
<servlet-class>...LetsencryptServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>letsencrypt</servlet-name>
<url-pattern>/.well-known/acme-challenge/*</url-pattern>
</servlet-mapping>
Of course, be sure that the servlet class has the full classpath for your created Servlet.
That blog post also deals with the other steps necessary to generate and install the certificate.
Ian: Are you sure that you were deploying the servlet well? check the logs, make sure that you are testing the right version.. maybe you had a compilation issue..
Cheers
I ran into this problem trying to serve an assetlinks.json
file. It would indeed appear that folders starting with a . are not accessible within the static context in App Engine. A more generic version of João Antunes workaround is as follows.
First, create the folder without the . at the start and place any required files inside it.
We then need to create a servlet that will respond with the correct data when a request to the hidden folder is received.
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
/**
* Created by Will Calderwood on 17/05/2017.
* <p>
* It would appear to not be possible to upload hidden folders to app engine. So when files need
* to be served from a hidden folder the URL can be bounced through this servlet
*/
public class StaticFileServer extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// We'll remove the dots from the path
String uri = req.getRequestURI().replace("/.", "/");
// Do anything else that needs doing here
if (uri.toLowerCase().contains(".json")) {
resp.setContentType("application/json");
}
// Read and return the resource from the non-hidden folder
try (InputStream in = getServletContext().getResourceAsStream(uri)) {
if (in == null){
resp.sendError(404);
return;
}
byte[] buffer = new byte[8192];
int count;
while ((count = in.read(buffer)) > 0) {
resp.getOutputStream().write(buffer, 0, count);
}
}
}
}
Then add the following to your web.xml
file to point the hidden folder at our servlet
<servlet>
<servlet-name>StaticFileServer</servlet-name>
<servlet-class>main.com.you.StaticFileServer</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>StaticFileServer</servlet-name>
<url-pattern>/.well-known/*</url-pattern>
</servlet-mapping>