mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-13 17:05:43 +01:00
improve GitCGIServlet
This commit is contained in:
@@ -30,6 +30,17 @@ public class GitConfig extends SimpleRepositoryConfig
|
|||||||
return gitBinary;
|
return gitBinary;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method description
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String getGitHttpBackend()
|
||||||
|
{
|
||||||
|
return gitHttpBackend;
|
||||||
|
}
|
||||||
|
|
||||||
//~--- set methods ----------------------------------------------------------
|
//~--- set methods ----------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -43,8 +54,22 @@ public class GitConfig extends SimpleRepositoryConfig
|
|||||||
this.gitBinary = gitBinary;
|
this.gitBinary = gitBinary;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method description
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param gitHttpBackend
|
||||||
|
*/
|
||||||
|
public void setGitHttpBackend(String gitHttpBackend)
|
||||||
|
{
|
||||||
|
this.gitHttpBackend = gitHttpBackend;
|
||||||
|
}
|
||||||
|
|
||||||
//~--- fields ---------------------------------------------------------------
|
//~--- fields ---------------------------------------------------------------
|
||||||
|
|
||||||
/** Field description */
|
/** Field description */
|
||||||
private String gitBinary = "git";
|
private String gitBinary = "git";
|
||||||
|
|
||||||
|
/** Field description */
|
||||||
|
private String gitHttpBackend = "git-http-backend";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,8 +9,11 @@ package sonia.scm.web;
|
|||||||
|
|
||||||
//~--- non-JDK imports --------------------------------------------------------
|
//~--- non-JDK imports --------------------------------------------------------
|
||||||
|
|
||||||
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.Singleton;
|
import com.google.inject.Singleton;
|
||||||
|
|
||||||
|
import sonia.scm.repository.GitConfig;
|
||||||
|
import sonia.scm.repository.GitRepositoryHandler;
|
||||||
import sonia.scm.web.cgi.AbstractCGIServlet;
|
import sonia.scm.web.cgi.AbstractCGIServlet;
|
||||||
import sonia.scm.web.cgi.EnvList;
|
import sonia.scm.web.cgi.EnvList;
|
||||||
|
|
||||||
@@ -46,18 +49,47 @@ public class GitCGIServlet extends AbstractCGIServlet
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
|
*
|
||||||
|
* @throws ServletException
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected EnvList createEnvironment()
|
protected EnvList createBaseEnvironment() throws ServletException
|
||||||
{
|
{
|
||||||
EnvList list = super.createEnvironment();
|
EnvList list = super.createBaseEnvironment();
|
||||||
|
|
||||||
list.set(ENV_PROJECT_ROOT, "/tmp/git");
|
|
||||||
list.set(ENV_HTTP_EXPORT_ALL, "");
|
list.set(ENV_HTTP_EXPORT_ALL, "");
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method description
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param baseEnvironment
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*
|
||||||
|
* @throws ServletException
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected EnvList createRequestEnvironment(EnvList baseEnvironment)
|
||||||
|
throws ServletException
|
||||||
|
{
|
||||||
|
GitConfig config = repositoryHandler.getConfig();
|
||||||
|
|
||||||
|
if (config == null)
|
||||||
|
{
|
||||||
|
throw new ServletException("git is not configured");
|
||||||
|
}
|
||||||
|
|
||||||
|
EnvList env = new EnvList(baseEnvironment);
|
||||||
|
|
||||||
|
env.set(ENV_PROJECT_ROOT, config.getRepositoryDirectory().getPath());
|
||||||
|
|
||||||
|
return env;
|
||||||
|
}
|
||||||
|
|
||||||
//~--- get methods ----------------------------------------------------------
|
//~--- get methods ----------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -75,6 +107,19 @@ public class GitCGIServlet extends AbstractCGIServlet
|
|||||||
protected File getCommand(HttpServletRequest req)
|
protected File getCommand(HttpServletRequest req)
|
||||||
throws ServletException, IOException
|
throws ServletException, IOException
|
||||||
{
|
{
|
||||||
return new File("/opt/local/libexec/git-core/git-http-backend/");
|
GitConfig config = repositoryHandler.getConfig();
|
||||||
|
|
||||||
|
if (config == null)
|
||||||
|
{
|
||||||
|
throw new ServletException("git is not configured");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new File(config.getGitHttpBackend());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//~--- fields ---------------------------------------------------------------
|
||||||
|
|
||||||
|
/** Field description */
|
||||||
|
@Inject
|
||||||
|
private GitRepositoryHandler repositoryHandler;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,11 @@ registerConfigPanel({
|
|||||||
name: 'baseUrl',
|
name: 'baseUrl',
|
||||||
fieldLabel: 'Base URL',
|
fieldLabel: 'Base URL',
|
||||||
allowBlank : false
|
allowBlank : false
|
||||||
|
},{
|
||||||
|
xtype : 'textfield',
|
||||||
|
fieldLabel : 'Git-Http-Backend',
|
||||||
|
name : 'gitHttpBackend',
|
||||||
|
allowBlank : false
|
||||||
}],
|
}],
|
||||||
|
|
||||||
onSubmit: function(values){
|
onSubmit: function(values){
|
||||||
|
|||||||
@@ -56,8 +56,9 @@ public abstract class AbstractCGIServlet extends HttpServlet
|
|||||||
@Override
|
@Override
|
||||||
public void init() throws ServletException
|
public void init() throws ServletException
|
||||||
{
|
{
|
||||||
cgiRunner = new CGIRunner(getServletContext(), createEnvironment(),
|
cgiRunner = new CGIRunner(getServletContext(), getCmdPrefix(),
|
||||||
getCmdPrefix(), isExitStateIgnored());
|
isExitStateIgnored());
|
||||||
|
baseEnvironment = createBaseEnvironment();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -65,8 +66,10 @@ public abstract class AbstractCGIServlet extends HttpServlet
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
|
*
|
||||||
|
* @throws ServletException
|
||||||
*/
|
*/
|
||||||
protected EnvList createEnvironment()
|
protected EnvList createBaseEnvironment() throws ServletException
|
||||||
{
|
{
|
||||||
EnvList env = new EnvList();
|
EnvList env = new EnvList();
|
||||||
Enumeration e = getInitParameterNames();
|
Enumeration e = getInitParameterNames();
|
||||||
@@ -94,6 +97,22 @@ public abstract class AbstractCGIServlet extends HttpServlet
|
|||||||
return env;
|
return env;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method description
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param baseEnvironment
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*
|
||||||
|
* @throws ServletException
|
||||||
|
*/
|
||||||
|
protected EnvList createRequestEnvironment(EnvList baseEnvironment)
|
||||||
|
throws ServletException
|
||||||
|
{
|
||||||
|
return new EnvList(baseEnvironment);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method description
|
* Method description
|
||||||
*
|
*
|
||||||
@@ -108,7 +127,8 @@ public abstract class AbstractCGIServlet extends HttpServlet
|
|||||||
protected void service(HttpServletRequest req, HttpServletResponse resp)
|
protected void service(HttpServletRequest req, HttpServletResponse resp)
|
||||||
throws ServletException, IOException
|
throws ServletException, IOException
|
||||||
{
|
{
|
||||||
cgiRunner.exec(getCommand(req), req.getPathInfo(), req, resp);
|
cgiRunner.exec(createRequestEnvironment(baseEnvironment), getCommand(req),
|
||||||
|
req.getPathInfo(), req, resp);
|
||||||
}
|
}
|
||||||
|
|
||||||
//~--- get methods ----------------------------------------------------------
|
//~--- get methods ----------------------------------------------------------
|
||||||
@@ -124,10 +144,6 @@ public abstract class AbstractCGIServlet extends HttpServlet
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
;
|
|
||||||
|
|
||||||
//~--- get methods ----------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method description
|
* Method description
|
||||||
*
|
*
|
||||||
@@ -139,10 +155,11 @@ public abstract class AbstractCGIServlet extends HttpServlet
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
;
|
|
||||||
|
|
||||||
//~--- fields ---------------------------------------------------------------
|
//~--- fields ---------------------------------------------------------------
|
||||||
|
|
||||||
|
/** Field description */
|
||||||
|
private EnvList baseEnvironment;
|
||||||
|
|
||||||
/** Field description */
|
/** Field description */
|
||||||
private CGIRunner cgiRunner;
|
private CGIRunner cgiRunner;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,11 +55,10 @@ public class CGIRunner
|
|||||||
* @param cmdPrefix
|
* @param cmdPrefix
|
||||||
* @param ignoreExitState
|
* @param ignoreExitState
|
||||||
*/
|
*/
|
||||||
public CGIRunner(ServletContext context, EnvList environment,
|
public CGIRunner(ServletContext context,
|
||||||
String cmdPrefix, boolean ignoreExitState)
|
String cmdPrefix, boolean ignoreExitState)
|
||||||
{
|
{
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.environment = environment;
|
|
||||||
this.cmdPrefix = cmdPrefix;
|
this.cmdPrefix = cmdPrefix;
|
||||||
this.ignoreExitState = ignoreExitState;
|
this.ignoreExitState = ignoreExitState;
|
||||||
}
|
}
|
||||||
@@ -77,7 +76,7 @@ public class CGIRunner
|
|||||||
*
|
*
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public void exec(File command, String pathInfo, HttpServletRequest req,
|
public void exec(EnvList environment, File command, String pathInfo, HttpServletRequest req,
|
||||||
HttpServletResponse res)
|
HttpServletResponse res)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
@@ -99,39 +98,37 @@ public class CGIRunner
|
|||||||
pathTranslated = path;
|
pathTranslated = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
EnvList env = new EnvList(environment);
|
|
||||||
|
|
||||||
// these ones are from "The WWW Common Gateway Interface Version 1.1"
|
// these ones are from "The WWW Common Gateway Interface Version 1.1"
|
||||||
// look at :
|
// look at :
|
||||||
// http://Web.Golux.Com/coar/cgi/draft-coar-cgi-v11-03-clean.html#6.1.1
|
// http://Web.Golux.Com/coar/cgi/draft-coar-cgi-v11-03-clean.html#6.1.1
|
||||||
env.set("AUTH_TYPE", req.getAuthType());
|
environment.set("AUTH_TYPE", req.getAuthType());
|
||||||
env.set("CONTENT_LENGTH", Integer.toString(len));
|
environment.set("CONTENT_LENGTH", Integer.toString(len));
|
||||||
env.set("CONTENT_TYPE", req.getContentType());
|
environment.set("CONTENT_TYPE", req.getContentType());
|
||||||
env.set("GATEWAY_INTERFACE", "CGI/1.1");
|
environment.set("GATEWAY_INTERFACE", "CGI/1.1");
|
||||||
|
|
||||||
if ((pathInfo != null) && (pathInfo.length() > 0))
|
if ((pathInfo != null) && (pathInfo.length() > 0))
|
||||||
{
|
{
|
||||||
env.set("PATH_INFO", pathInfo);
|
environment.set("PATH_INFO", pathInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
env.set("PATH_TRANSLATED", pathTranslated);
|
environment.set("PATH_TRANSLATED", pathTranslated);
|
||||||
env.set("QUERY_STRING", req.getQueryString());
|
environment.set("QUERY_STRING", req.getQueryString());
|
||||||
env.set("REMOTE_ADDR", req.getRemoteAddr());
|
environment.set("REMOTE_ADDR", req.getRemoteAddr());
|
||||||
env.set("REMOTE_HOST", req.getRemoteHost());
|
environment.set("REMOTE_HOST", req.getRemoteHost());
|
||||||
|
|
||||||
// The identity information reported about the connection by a
|
// The identity information reported about the connection by a
|
||||||
// RFC 1413 [11] request to the remote agent, if
|
// RFC 1413 [11] request to the remote agent, if
|
||||||
// available. Servers MAY choose not to support this feature, or
|
// available. Servers MAY choose not to support this feature, or
|
||||||
// not to request the data for efficiency reasons.
|
// not to request the data for efficiency reasons.
|
||||||
// "REMOTE_IDENT" => "NYI"
|
// "REMOTE_IDENT" => "NYI"
|
||||||
env.set("REMOTE_USER", req.getRemoteUser());
|
environment.set("REMOTE_USER", req.getRemoteUser());
|
||||||
env.set("REQUEST_METHOD", req.getMethod());
|
environment.set("REQUEST_METHOD", req.getMethod());
|
||||||
env.set("SCRIPT_NAME", scriptName);
|
environment.set("SCRIPT_NAME", scriptName);
|
||||||
env.set("SCRIPT_FILENAME", scriptPath);
|
environment.set("SCRIPT_FILENAME", scriptPath);
|
||||||
env.set("SERVER_NAME", req.getServerName());
|
environment.set("SERVER_NAME", req.getServerName());
|
||||||
env.set("SERVER_PORT", Integer.toString(req.getServerPort()));
|
environment.set("SERVER_PORT", Integer.toString(req.getServerPort()));
|
||||||
env.set("SERVER_PROTOCOL", req.getProtocol());
|
environment.set("SERVER_PROTOCOL", req.getProtocol());
|
||||||
env.set("SERVER_SOFTWARE", context.getServerInfo());
|
environment.set("SERVER_SOFTWARE", context.getServerInfo());
|
||||||
|
|
||||||
Enumeration enm = req.getHeaderNames();
|
Enumeration enm = req.getHeaderNames();
|
||||||
|
|
||||||
@@ -140,11 +137,11 @@ public class CGIRunner
|
|||||||
String name = (String) enm.nextElement();
|
String name = (String) enm.nextElement();
|
||||||
String value = req.getHeader(name);
|
String value = req.getHeader(name);
|
||||||
|
|
||||||
env.set("HTTP_" + name.toUpperCase().replace('-', '_'), value);
|
environment.set("HTTP_" + name.toUpperCase().replace('-', '_'), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// these extra ones were from printenv on www.dev.nomura.co.uk
|
// these extra ones were from printenv on www.dev.nomura.co.uk
|
||||||
env.set("HTTPS", (req.isSecure()
|
environment.set("HTTPS", (req.isSecure()
|
||||||
? "ON"
|
? "ON"
|
||||||
: "OFF"));
|
: "OFF"));
|
||||||
|
|
||||||
@@ -172,8 +169,8 @@ public class CGIRunner
|
|||||||
}
|
}
|
||||||
|
|
||||||
Process p = (dir == null)
|
Process p = (dir == null)
|
||||||
? Runtime.getRuntime().exec(execCmd, env.getEnvArray())
|
? Runtime.getRuntime().exec(execCmd, environment.getEnvArray())
|
||||||
: Runtime.getRuntime().exec(execCmd, env.getEnvArray(), dir);
|
: Runtime.getRuntime().exec(execCmd, environment.getEnvArray(), dir);
|
||||||
|
|
||||||
// hook processes input to browser's output (async)
|
// hook processes input to browser's output (async)
|
||||||
final InputStream inFromReq = req.getInputStream();
|
final InputStream inFromReq = req.getInputStream();
|
||||||
@@ -327,17 +324,6 @@ public class CGIRunner
|
|||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public EnvList getEnvironment()
|
|
||||||
{
|
|
||||||
return environment;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method description
|
* Method description
|
||||||
*
|
*
|
||||||
@@ -373,17 +359,6 @@ public class CGIRunner
|
|||||||
this.context = context;
|
this.context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param environment
|
|
||||||
*/
|
|
||||||
public void setEnvironment(EnvList environment)
|
|
||||||
{
|
|
||||||
this.environment = environment;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method description
|
* Method description
|
||||||
*
|
*
|
||||||
@@ -481,9 +456,6 @@ public class CGIRunner
|
|||||||
/** Field description */
|
/** Field description */
|
||||||
private ServletContext context;
|
private ServletContext context;
|
||||||
|
|
||||||
/** Field description */
|
|
||||||
private EnvList environment;
|
|
||||||
|
|
||||||
/** Field description */
|
/** Field description */
|
||||||
private boolean ignoreExitState;
|
private boolean ignoreExitState;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ public class EnvList
|
|||||||
* Constructs ...
|
* Constructs ...
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
EnvList()
|
public EnvList()
|
||||||
{
|
{
|
||||||
envMap = new HashMap<String, String>();
|
envMap = new HashMap<String, String>();
|
||||||
}
|
}
|
||||||
@@ -38,13 +38,26 @@ public class EnvList
|
|||||||
*
|
*
|
||||||
* @param l
|
* @param l
|
||||||
*/
|
*/
|
||||||
EnvList(EnvList l)
|
public EnvList(EnvList l)
|
||||||
{
|
{
|
||||||
envMap = new HashMap<String, String>(l.envMap);
|
envMap = new HashMap<String, String>(l.envMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
//~--- methods --------------------------------------------------------------
|
//~--- methods --------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method description
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean containsKey(String key)
|
||||||
|
{
|
||||||
|
return envMap.containsKey(key);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method description
|
* Method description
|
||||||
*
|
*
|
||||||
@@ -57,11 +70,6 @@ public class EnvList
|
|||||||
return envMap.toString();
|
return envMap.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean containsKey( String key )
|
|
||||||
{
|
|
||||||
return envMap.containsKey(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
//~--- get methods ----------------------------------------------------------
|
//~--- get methods ----------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user