通过PUT

时间:2018-07-23 23:12:47

标签: java nginx

当前,我正在研究在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,但是如果有人有更好的建议,随时纠正我。

0 个答案:

没有答案