自定义重写规则在多站点上发送404标头

时间:2019-04-08 作者:JacobTheDev

I have a custom rewrite rule which rewrites /wp-content/themes/my-theme/manifest.json to /index.php?manifest=true. This generates some JSON code for progressive web app functionality, and generally works great.

On a multisite install, however, the manifest loads correctly, but still sends a 404 header. I verified that this specific theme does work fine with a normal WordPress site, but in a multisite install, it always seems to send the 404 header.

enter image description here

Some notes:

  • I\'ve tried using status_header(200), and header("HTTP/1.1 200 OK") manually, but neither of those make a difference
  • I\'ve tried setting $wp->is_404 to false, but that does nothing
  • I\'ve flushed the permalinks, but that does nothing

Rewrite Rule PHP:

// set up rewirte rules for PWA functionality
function fvpd_pwa_rewrite_rules() {
    add_rewrite_endpoint("manifest", EP_NONE);
    add_rewrite_rule(substr(parse_url(get_template_directory_uri(), PHP_URL_PATH), 1) . "/manifest\\.json$", "index.php?manifest=true", "top");
}
add_action("init", "fvpd_pwa_rewrite_rules");

manifest.json PHP:

// construct a manifest when the user visits {theme_folder}/manifest.json
function fvpd_construct_manifest() {
    if (get_query_var("manifest")) {
        header("Content-Type: application/json");

        $name             = fvpd_get_field("full_name", "pwa");
        $short_name       = fvpd_get_field("short_name", "pwa");
        $background_color = fvpd_get_field("background_color", "pwa");
        $theme_color      = fvpd_get_field("theme_color", "pwa");

        $manifest = array(
            "start_url"        => "/",
            "display"          => "standalone",
            "name"             => $name ? $name : "Fox Valley Park District - DEV",
            "short_name"       => $short_name ? $short_name : "FVPD",
            "background_color" => $background_color ? $background_color : "#E58F1A",
            "theme_color"      => $theme_color ? $theme_color : "#E58F1A",
            "icons"            => array(
                array(
                    "src"   => get_theme_file_uri("assets/media/android/splash-icon-512x512.png"),
                    "type"  => "image/png",
                    "sizes" => "512x512",
                ),
                array(
                    "src"   => get_theme_file_uri("assets/media/android/launcher-icon-192x192.png"),
                    "type"  => "image/png",
                    "sizes" => "192x192",
                ),
                array(
                    "src"   => get_theme_file_uri("assets/media/android/launcher-icon-144x144.png"),
                    "type"  => "image/png",
                    "sizes" => "144x144",
                ),
                array(
                    "src"   => get_theme_file_uri("assets/media/android/launcher-icon-96x96.png"),
                    "type"  => "image/png",
                    "sizes" => "96x96",
                ),
                array(
                    "src"   => get_theme_file_uri("assets/media/android/launcher-icon-72x72.png"),
                    "type"  => "image/png",
                    "sizes" => "72x72",
                ),
                array(
                    "src"   => get_theme_file_uri("assets/media/android/launcher-icon-48x48.png"),
                    "type"  => "image/png",
                    "sizes" => "48x48",
                ),
            ),
        );

        echo json_encode($manifest); exit;
    }
}
add_action("wp", "fvpd_construct_manifest");

URL in questions:

https://www.foxvalleyparkdistrict.org/wp-content/themes/fox-valley-park-district/manifest.json

This does not affect my other custom rewrite, which points /offline/ to load a custom template.

https://www.foxvalleyparkdistrict.org/offline/

Why is the 404 header being sent, and how can I fix it?


UPDATE 1:

I tried some of the advice below, but to no avail. I do have some additional information that may help, however. I tested changing the rewrite to /manifest.json instead of /wp-content/themes/my-theme/manifest.json, and that actually worked! This gave me an idea, and so I tried the following:

| URL                        | Status | Folder Exists | WordPress Folder |
|:--------------------------:|:------:|:-------------:|:----------------:|
| /manifest.json             | 200    | N/A           | N/A              |
| /wp-admin/manifest.json    | 404    | true          | true             |
| /wp-content/manifest.json  | 404    | true          | true             |
| /wp-includes/manifest.json | 404    | true          | true             |
| /cgi-bin/manifest.json     | 403    | true          | false            |
| /custom/manifest.json      | 200    | false         | false            |
| /custom/manifest.json      | 200    | true          | false            |

It seems that if the rewrite is returning a 404 header only when set to an existing WordPress folder. My suspicion is that the rewrite engine is partially ignoring rules to /wp-* folders.

I may end up just keeping the rewrite at /manifest.json, but that creatures a problem if in the future we where to set up additional sites like https://example.com/second-site/, although that could probably be fixed by rewriting to the WordPress root instead of the server root.

UPDATE 2: .htaccess contents is visible here: https://gist.github.com/JacobDB/1531b75c8b8c79117516019225bb7732

4 个回复
最合适的回答,由SO网友:filipecsweb 整理而成

基本上,您做错了一件事,那就是实际上有一个名为manifest.json 在…内/wp-content/themes/your-theme.

因此,首先,删除您的文件/wp-content/themes/your-theme/manifest.json.

然后,在你的functions.php 文件您可以将重写规则设置为:

function fvpd_pwa_rewrite_rules() {
    add_rewrite_endpoint( "manifest", EP_NONE );
    add_rewrite_rule( substr( parse_url( get_template_directory_uri(), PHP_URL_PATH ), 1 ) . "/manifest.json/?$", "index.php?manifest=true", "top" );
}

add_action( "init", "fvpd_pwa_rewrite_rules" );
json内容为:

// construct a manifest when the user visits {theme_folder}/manifest.json
function fvpd_construct_manifest() {
    if ( get_query_var( "manifest" ) ) {
        $name             = fvpd_get_field( "full_name", "pwa" );
        $short_name       = fvpd_get_field( "short_name", "pwa" );
        $background_color = fvpd_get_field( "background_color", "pwa" );
        $theme_color      = fvpd_get_field( "theme_color", "pwa" );

        $manifest = array(
            "start_url"        => "/",
            "display"          => "standalone",
            "name"             => $name ? $name : "Fox Valley Park District - DEV",
            "short_name"       => $short_name ? $short_name : "FVPD",
            "background_color" => $background_color ? $background_color : "#E58F1A",
            "theme_color"      => $theme_color ? $theme_color : "#E58F1A",
            "icons"            => array(
                array(
                    "src"   => get_theme_file_uri( "assets/media/android/splash-icon-512x512.png" ),
                    "type"  => "image/png",
                    "sizes" => "512x512",
                ),
                array(
                    "src"   => get_theme_file_uri( "assets/media/android/launcher-icon-192x192.png" ),
                    "type"  => "image/png",
                    "sizes" => "192x192",
                ),
                array(
                    "src"   => get_theme_file_uri( "assets/media/android/launcher-icon-144x144.png" ),
                    "type"  => "image/png",
                    "sizes" => "144x144",
                ),
                array(
                    "src"   => get_theme_file_uri( "assets/media/android/launcher-icon-96x96.png" ),
                    "type"  => "image/png",
                    "sizes" => "96x96",
                ),
                array(
                    "src"   => get_theme_file_uri( "assets/media/android/launcher-icon-72x72.png" ),
                    "type"  => "image/png",
                    "sizes" => "72x72",
                ),
                array(
                    "src"   => get_theme_file_uri( "assets/media/android/launcher-icon-48x48.png" ),
                    "type"  => "image/png",
                    "sizes" => "48x48",
                ),
            ),
        );

        wp_send_json( $manifest );
    }
}

add_action( "wp", "fvpd_construct_manifest" );
注意WordPress函数的用法wp_send_json() 它为您处理必要的头、json转换等。

确保刷新永久链接并测试URLhttp://localhost/wp-content/themes/your-theme/manifest.json.

如果上述方法仍然不能解决您的问题,则意味着您也无法按照WordPress标准正确设置web服务器NGINX或APACHE。

SO网友:ChristopherJones

不久前,我遇到了类似的问题。我提出了一个答案,它并没有解决404问题,但在解决这个问题时采用了不同的方法,假设这个json文件的内容不是按用户设置的。

与其让PHP在json文件中运行并更改文件头以反映更多内容,为什么不使用清单呢。php文件坐在旁边,编写清单。json文件:

themes/fox-valley-park-district/
  \\__ manifest.php
  \\__ manifest.json
在php文件中完成上面列出的所有工作,并删除其中的add\\u action hook调用。可能您的php文件如下所示:

<?php
  function fvpd_construct_manifest() {

    // Compile what you need

    return $manifest_output;
  }

  $manifest_json_file = \'manifest.json\';
  $json_data = fvpd_construct_manifest();
  $json_data_encoded = json_encode($json_data);

  // You may need to deal with permission issues on that .json file
  file_put_contents(__DIR__ .\'/\'.$manifest_json_file, $json_data_encoded);
然后运行cron来点击清单。php。同样,这是一种不同的方法和答案,但并没有回答具体的404问题。如果我离这里很远。。。。我很乐意删除这个答案。

希望有帮助,祝你好运!!

SO网友:Nathan Powell

我想你只是打错了字。更改以下内容使我可以在multisite上工作。

尝试更改此选项:

    add_rewrite_rule(substr(parse_url(get_template_directory_uri(), PHP_URL_PATH), 1) . "/manifest\\.json$", "index.php?manifest=true", "top");
对此:

    add_rewrite_rule(substr(parse_url(get_template_directory_uri(), PHP_URL_PATH), 1) . "/manifest.json", "index.php?manifest=true", "top");

SO网友:Michael Ecklund

我想那是因为.json 被视为“静态文件”。这意味着请求不会触发PHP。这种路由可能需要在服务器级别进行。

相关推荐

使用WordPress MultiSite(WPMS),每个创建的站点都有一个远程数据库

所以,我很想找到一种方法,为每个新添加的子站点使用具有不同远程数据库的WPM。我所知道的。我知道远程数据库可以位于其自己的服务器上,以允许远程站点连接使用DB用户的附加权限,并以%通配符的形式将IP绑定到DB或IP地址(如果您的服务器是网络的一部分)。请参见:https://www.digitalocean.com/community/tutorials/how-to-set-up-a-remote-database-to-optimize-site-performance-with-mysql或对我来说