Pequeño pero potente servidor web multiproceso escrito completamente en Java SE y luego portado a Android.
El servidor implementa la mayor parte de la especificación HTTP 1.1 y proporciona API Servlet personalizada que puede usarse para manejar páginas dinámicas. La API Servlet está diseñada después de la API oficial javax.servlet , pero no es compatible. Las páginas dinámicas admiten cookies, sesiones, cargas de archivos y cualquier otra cosa para crear una aplicación web común.
El envoltorio de gradle proporcionado debe usarse para construir la aplicación:
./gradlew clean build Al ejecutar la compilación completa por primera vez, primero debe instalar el SDK de Android. Puede instalarlo manualmente o usar el siguiente script que descarga e instala todas las dependencias requeridas en ~/android-sdk .
./installsdk.sh Para que las cosas funcionen después de iniciar sesión e iniciar sesión, configure la variable de entorno ANDROID_HOME :
echo " export ANDROID_HOME=~/android-sdk " >> ~ /.bashrc && source ~ /.bashrcEl subproyecto HTTP es el corazón de la aplicación y es independiente en la plataforma Android.
De hecho, la aplicación Android fue solo un intento de encontrar un uso más práctico de la implementación experimental del protocolo HTTP.
Uno de los objetivos de diseño era mantener el artefacto resultante pequeño de tamaño y minimalista en términos de dependencia de otras bibliotecas: no requiere ningún componente de terceros , toda la implementación del protocolo HTTP se basa en los datos de análisis de los enchufes TCP sin procesar.
Una vez que el paquete ro.polak.http es lo suficientemente maduro, se lanzará como un artefacto independiente.
El subproyecto se puede probar de la siguiente manera:
./gradlew :http:clean :http:check -PskipAndroidBuildEl código de paquete original se ha refactorizado y cubierto con unidades y pruebas de integración. La cobertura del código debe mantenerse por encima del 90%.
Todo el código de aplicación está dirigido a Java 7. También se compila para las versiones SDK de Android <19 (intente con recursos no es compatible, use ioutilidades. CLOSISILLENTE (cierre) en un bloque finally como una alternativa al cerrar las transmisiones).
Otra restricción de compatibilidad es que se usa Random en lugar de ThreadLocalRandom para generar secuencias aleatorias en StringUtilidades
Las pruebas de mutación se pueden ejecutar ejecutando el siguiente comando:
./gradlew :http:clean :http:pitest -PskipAndroidBuild Los resultados se pueden encontrar en http/build/reports/pitest/ro.polak.http/index.html y http/build/reports/pitest/ro.polak.http/mutation.xml .
El servidor independiente se puede usar para agrupar el subproyecto http en una implementación de servidor ejecutable. El subproyecto CLI también es independiente en la plataforma Android, no está incluido con el APK principal.
./gradlew :cli:bootRun -PskipAndroidBuildTambién es posible construir un "Uber-Jar" y usarlo como una aplicación independiente:
./gradlew :cli:fatJar -PskipAndroidBuild El artefacto resultante se puede agarrar desde ./cli/build/libs/cli-all.jar .
El jar de servidor independiente se puede ejecutar en cualquier máquina con el siguiente comando:
java -jar ./cli/build/libs/cli-all.jarjava -jar ./cli/build/libs/cli-all.jar
-Dserver.port=8888
-Dserver.static.path=/www/public_htmlPara obtener una lista completa de los parámetros disponibles, consulte httpd.properties.

Una aplicación de demostración se implementa automáticamente en Heroku y se puede llegar a:
Tenga en cuenta que la aplicación implementada no contiene la aplicación de administración , ya que solo está disponible para Android. Consulte PROCFILE para la descripción de la implementación.
package example ;
import ro . polak . http . servlet . HttpServletRequest ;
import ro . polak . http . servlet . HttpServletResponse ;
import ro . polak . http . servlet . HttpServlet ;
public class HelloWorld extends HttpServlet {
@ Override
public void service ( HttpServletRequest request , HttpServletResponse response ) {
response . getWriter (). print ( "Hello World!" );
}
} package example ;
import java . io . IOException ;
import ro . polak . http . exception . ServletException ;
import ro . polak . http . servlet . Filter ;
import ro . polak . http . servlet . FilterChain ;
import ro . polak . http . servlet . FilterConfig ;
import ro . polak . http . servlet . HttpServletRequest ;
import ro . polak . http . servlet . HttpServletResponse ;
public class RequestLoggingFilter implements Filter {
private static final Logger LOGGER = Logger . getLogger ( RequestLoggingFilter . class . getName ());
@ Override
public void init ( FilterConfig filterConfig ) throws ServletException {
// Do nothing
}
@ Override
public void doFilter ( HttpServletRequest request , HttpServletResponse response ,
FilterChain filterChain ) throws IOException , ServletException {
LOGGER . fine ( "Handling incoming request " + request . getRequestURL ());
filterChain . doFilter ( request , response );
}
}Los servlets de ejemplo se pueden encontrar en http/src/main/java/ejemplo.
Se puede verificar un uso práctico de filtros en SecurityFilter.java y logroutFilter.java de la aplicación administrativa.
ImplementmentDescriptorBuilder es una alternativa de API al enfoque web.xml tradicional que tiene como objetivo facilitar el registro de la construcción y el filtro de mapeo de servlet. Ver código de ejemplo a continuación.
package example ;
import java . util . List ;
import java . util . regex . Pattern ;
import ro . polak . http . configuration . DeploymentDescriptorBuilder ;
import ro . polak . http . configuration . ServerConfig ;
import ro . polak . http . session . storage . SessionStorage ;
class DeploymentDescriptorFactory {
public List < ServletContextWrapper > buildDeploymentDescriptor ( SessionStorage sessionStorage ,
ServerConfig serverConfig ) {
return DeploymentDescriptorBuilder . create ()
. withSessionStorage ( sessionStorage )
. withServerConfig ( serverConfig )
. addServletContext ()
. withContextPath ( "/example" )
. addFilter ()
. withUrlPattern ( Pattern . compile ( "^.*$" ))
. withUrlExcludedPattern ( Pattern . compile ( "^/(?:Login|Logout)" ))
. withFilterClass ( SecurityFilter . class )
. end ()
. addFilter ()
. withUrlPattern ( Pattern . compile ( "^/Logout$" ))
. withFilterClass ( LogoutFilter . class )
. end ()
. addServlet ()
. withUrlPattern ( Pattern . compile ( "^/Index$" ))
. withServletClass ( Index . class )
. end ()
. addServlet ()
. withUrlPattern ( Pattern . compile ( "^/$" ))
. withServletClass ( Index . class )
. end ()
. end ()
. build ();
}
}Servir recursos estáticos se implementa utilizando defaultservlet
La carga real de recursos se implementa registrando una instancia de recursos en la configuración del servidor.
Actualmente hay dos proveedores de recursos implementados
package ro . polak . http . resource . provider ;
import ro . polak . http . servlet . impl . HttpServletRequestImpl ;
import ro . polak . http . servlet . impl . HttpServletResponseImpl ;
import java . io . IOException ;
public class DummyResourceProvider implements ResourceProvider {
/**
* Tells whether this resource provider can load resource for given path.
*/
@ Override
public boolean canLoad ( final String path ) {
return false ; // TODO Add some logic
}
/**
* Loads the resource for the given path by copying the stream to the response.getOutputStream().
*/
@ Override
public void load ( final String path ,
final HttpServletRequestImpl request ,
final HttpServletResponseImpl response ) throws IOException {
// TODO Load the stream to response.getOutputStream();
}
/**
* Shuts down the resource provider if necessary, usually closes all open resources.
*/
@ Override
public void shutdown () {
}
}El siguiente ejemplo presenta cómo integrar el motor de plantilla JTWIG.
Primero debe agregar la dependencia de JTWIG en su archivo de Gradle:
// ...
dependencies {
// ...
compile ' org.jtwig:jtwig-core:5.87.0.RELEASE '
}
// ...Luego funciona fuera de la caja:
package example ;
import org . jtwig . JtwigModel ;
import org . jtwig . JtwigTemplate ;
import ro . polak . http . exception . ServletException ;
import ro . polak . http . servlet . HttpServlet ;
import ro . polak . http . servlet . HttpServletRequest ;
import ro . polak . http . servlet . HttpServletResponse ;
public class Templating extends HttpServlet {
@ Override
public void service ( HttpServletRequest request , HttpServletResponse response )
throws ServletException {
JtwigTemplate template = JtwigTemplate . inlineTemplate ( "Hello {{ var }}" );
JtwigModel model = JtwigModel . newModel (). with ( "var" , "World" );
template . render ( model , response . getOutputStream ());
}
}






Si desea enviar un SMS real, elimine "& test = 1" de los parámetros de publicación.
SERVER_IP=192.168.1.1 ; SERVER_PORT=8080 ;
echo " Phone number: " ; read TO ; echo " Message: " ; read MESSAGE ;
wget -qO- --post-data " to= $TO &message= $MESSAGE &test=1 "
http:// $SERVER_IP : $SERVER_PORT /api/1.0/sms/sendAndroid HTTP Server utiliza íconos del paquete de "iconos web de frescos agrícolas" bellamente diseñados por FatCow Web Hosting. Estos conjuntos de iconos tienen licencia bajo una licencia Creative Commons Attribution 3.0.
El proyecto se comparte con la licencia GNU GPLV3.
Si está interesado en una licencia comercial dedicada, envíeme una línea en piotr [at] polak [dot] ro