当前,我正在研究在Glassfish服务器上运行的Vaadin Web应用程序项目。该项目的阶段之一涉及将文件发送到支持以下HTTP请求的用户指定的HTTP服务器:POST,PUT,DELETE和GET。为了进行测试,我创建了一个nginx服务器(位于localhost:80)作为目标服务器。在网上进行了一些搜索之后,我发现nginx本身不支持PUT命令(这是在项目生命周期中发出的第一个命令),因此我遵循了本文中的步骤:
How do I allow a PUT file request on Nginx server?
另外,请注意,我已经在要存储所有网站文件的目录上执行了chmod 777;这可能是无关紧要的,因为该问题似乎并没有直接处理权限,但是无论如何我都会包括这个细节。
当我尝试执行以下Java代码(Web应用程序项目通过Netbeans运行)时出现问题:
public int sendSchemaContextToPlace(MainUI ui){
//Shouldn't need to check is schemaContext is null because that happens beforehand inside RetrieverView
String charset = "utf-8";
String CRLF = "\r\n";
String trimmedPlace = ui.pathToYangRepoHTTP.trim();
String boundary = Long.toHexString(System.currentTimeMillis());
//ArrayList<File> listOfFilesToDelete = new ArrayList<>();
int cumulativeResponseCode = -1;
try {
//Be careful: getModules returns an immutable set
Set<Module> schemaModulesYang = allModulesAndSubModules(new HashSet<>(SCYang.getModules()), null);
//Notification.show("Got to outer scope");
//System.out.println("Just finished setdooutput");
//The following two commented out sections may be unnecessary since the files are directly
//created remotely with respect to their appropriate URLs; the connection is still necessary
//to see if the responsecode is ok
/*
*/
String directory = ui.hostName + "--SSH_IP: " + ui.ssh_ip + "--" + ui.platform + "/";
if (java.nio.file.Files.notExists(Paths.get(directory))) {
File newDir = new File("/var/www/html/" + directory);
newDir.mkdir();
}
for (Module m: schemaModulesYang) {
//File temp_module = new File("/var/www/html/" + directory + m.getName() + ".yang");
//temp_module.createNewFile();
URL url = new URL(trimmedPlace + (trimmedPlace.substring(trimmedPlace.length()-1).equals("/") ||
trimmedPlace.substring(trimmedPlace.length()-1).equals("\\") ? "" : "/") + directory + m.getName() + ".yang");
//File temp_module = new File(new URI("\\\\" + trimmedPlace + (trimmedPlace.substring(trimmedPlace.length()-1).equals("\\") ?
// "" : "\\") + m.getName() + ".yang"));
//temp_module.createNewFile();
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("PUT");
connection.setRequestProperty("charset", charset);
connection.setRequestProperty("Content-Type", "text/plain");
String sourceCode = "CANNOT PROCESS SOURCE CODE";
//Notification.show("Got inside for loop");
try {
sourceCode = (repoYang.getSchemaSource(YangTextSchemaSource.identifierFromFilename(m.getName() + (m.getRevision().isPresent()
? "@" + m.getRevision().get() : "" ) + ".yang"),
YangTextSchemaSource.class)).get().asCharSource(StandardCharsets.UTF_8).read();
}
catch (InterruptedException e) {
Notification.show(e.getMessage(), Notification.Type.ERROR_MESSAGE);
System.out.println(ExceptionUtils.getStackTrace(e));
}
catch (ExecutionException e) {
Notification.show(e.getMessage(), Notification.Type.ERROR_MESSAGE);
System.out.println(ExceptionUtils.getStackTrace(e));
}
catch (Exception e) {
System.out.println("Module parsing failure:");
System.out.println(ExceptionUtils.getStackTrace(e));
//Notification.show("Failed to parse the module " + m.getName() + " while attempting to write YANG source code to remote repository");
}
if (sourceCode.isEmpty()) {
System.out.println("Empty YANG file source code obtained for " + m.getName());
break;
}
//int yangLength = sourceCode.getBytes(StandardCharsets.UTF_8).length;
//connection.setRequestProperty("Content-Length", Integer.toString(yangLength));
PrintWriter fileWriter = new PrintWriter(connection.getOutputStream());
fileWriter.write(sourceCode);
fileWriter.flush();
fileWriter.close();
/*
PrintWriter trueWriter = new PrintWriter(temp_module);
trueWriter.write(sourceCode);
trueWriter.close();
*/
System.out.println("Finished parsing module with name: " + m.getName());
cumulativeResponseCode = connection.getResponseCode();
if (cumulativeResponseCode != 200) {
System.out.println("Broken due to bad response");
break;
}
}
}
catch (MalformedURLException e) {
System.out.printf("The URL you provided, %s, is in an incorrect format.", ui.pathToYangRepoHTTP);
}
catch (IOException e) {
System.out.print(ExceptionUtils.getStackTrace(e));
}
return cumulativeResponseCode;
}
基本上,一旦PUT请求没有为任何文件返回正确的响应,我就会停止该过程并返回错误代码。在我的情况下,该错误在for-each循环的第一次迭代期间发生,并且为404(找不到文件)。这对我来说确实有意义,因为实际上在循环内的URL中指定的文件不存在-但这应该是这样:毕竟,我认为对不存在的资源的PUT请求将创建该资源。 / p>
我的理解不正确吗?还是除了通过chmod'ing目录和上述帖子的解决方案中提到的dav_methods之外,还有其他步骤来通过PUT启用文件创建吗?
编辑:另外,如果此特定信息有用: 如果我取消注释手动创建文件的两行(for-each循环中处理temp_module的前两行),则不会出现404错误-我肯定会想到-但是PUT请求在其中没有任何作用案件。也就是说,文件仍然为空-如果我真的想填写它们,我必须使用temp_module(这是for-each循环底部附近的注释掉的部分)上的PrintWriter手动进行处理。
编辑2:好,所以我在第一次编辑中解决了这个问题。原来,我需要重新加载nginx(sudo nginx -s reload)。但是,我仍然没有解决第一个问题(如果我不事先手动创建文件,则会出现404问题)。
更新:因此,我四处寻找可能有助于解决此问题的外部库,发现了这一点:
https://memorynotfound.com/apache-httpclient-http-put-request-method-example/
不幸的是,Apache的HttpPut仍然为我抛出404。
更新2:好吧,我尝试替换手动目录创建行:
File newDir = new File("/var/www/html/" + directory);
newDir.mkdir();
带有MKCOL请求的(还将命令添加到了nginx配置中,然后又重新加载了nginx),它也为404。由于HttpURLConnection本身不支持MKCOL,因此我使用了Apache Jackrabbit库:
try (CloseableHttpClient httpclient = HttpClients.createDefault()) {
HttpMkcol dir = new HttpMkcol(trimmedPlace + (trimmedPlace.substring(trimmedPlace.length()-1).equals("/") ||
trimmedPlace.substring(trimmedPlace.length()-1).equals("\\") ? "" : "/") + directory);
ResponseHandler<String> rHandler = response -> {
int status = response.getStatusLine().getStatusCode();
if (status >= 200 && status < 300) {
HttpEntity entity = response.getEntity();
return entity != null ? EntityUtils.toString(entity) : null;
}
else {
throw new ClientProtocolException("Unexcepted response status " + status);
}
};
String responseBody = httpclient.execute(dir, rHandler);
System.out.println(responseBody);
}
这是基于此处看到的示例:
https://memorynotfound.com/apache-httpclient-http-put-request-method-example
除了使用HttpPut之外,其他都一样,我使用HttpMkcol。我真的不明白为什么会显示404-该目录从一开始就绝对不存在。实际上,基于RFC文档:
https://tools.ietf.org/html/rfc4918#section-9.3
它明确指出“如果Request-URI已经映射到资源, 则MKCOL必须失败。”在那种情况下,404怎么可能发生呢?在这一点上,我很确定这是一个(nginx)配置问题,因为PUT和MKCOL都返回404,但是如果有人有更好的建议,随时纠正我。