route – Eternal Night https://www.shuijingwanwq.com There is no problem not worth solving, and no technology not worth learning! Sun, 07 Jun 2026 13:45:22 +0000 en-US hourly 1 https://wordpress.org/?v=7.0 After deactivating self-built WireGuard from LetsVPN: Chengdu Mobile Broadband + Vultr Singapore node The measured network speed is very slow to review + pit dry goods https://www.shuijingwanwq.com/en/2026/05/03/10198/ https://www.shuijingwanwq.com/en/2026/05/03/10198/#respond Sun, 03 May 2026 09:15:36 +0000 https://www.shuijingwanwq.com/?p=10198 Post Views: 69

Since LetsVPN officially announced that the service was stopped, many friends who pursue privacy and self-use network have embarked on their own way to build Wireguard. Recently, a reader sent me an email consultation: I am like me, I have started a VULTR $5 per month Singapore entry model, and the Wireguard has been built. After visiting overseas platforms such as Binance, the network speed is very slow, and the loading is stuck. It is suspected that there is a problem with my configuration, and I want to know the specific reasons and solutions. as shown in Figure 1

Recently, a reader sent me an email consultation: I am like me, I have started a VULTR $5 per month Singapore entry model, and the Wireguard has been built. After visiting overseas platforms such as Binance, the network speed is very slow, and the loading is stuck. It is suspected that there is a problem with my configuration, and I want to know the specific reasons and solutions. as shown in Figure 1


In fact, this reader’s question is also a pit that many beginners can easily encounter after building Wireguard – there is generally a consensus on the selection of novice: the priority is to choose the Singapore computer room, the reason is very intuitive—— The physical distance from China to Singapore is close, the theoretical delay is lower, and it is more comfortable to visit overseas websites.
I am also using the same Vultr Singapore node to fully deploy Wireguard according to the tutorial, and the configuration is optimized in place, but the actual use has also encountered the same problem as this reader: open Binance slow loading, the page is often rotated, k The line market is obviously lagging behind, obviously the bandwidth is full, but the body feels very smooth.
So I made a complete ping Delay, routing tracking, bandwidth speed measurement, and real-life access experience. Wireguard, readers who are choosing a VPS room and line, make a practical reference for pit avoiding.

1. Personal measured environmental baseline

  • Local broadband: Chengdu, Sichuan, mobile home broadband (gigabit bandwidth)
  • VPS service provider: vultr
  • Computer room node: Singapore
  • Machine configuration: 1 core / 1G memory / 25G SSD / monthly traffic 2.5TB
  • Use scenarios: self-built WireGuard self-use, browsing overseas sites, market platform access
  • Configuration status: WireGuard private key public key, shunt rule, DNS, MTU, and keep-alive parameters have been adjusted to the optimal, no configuration errors, no firewall conflicts

2. The original data of the whole network measured

  1. Powershell ping delay test
PS C:\Users\Thinkpad> ping www.binance.com -n 30
正在 Ping dobbmei4jnjlh.cloudfront.net [18.64.211.66] 具有 32 字节的数据:
来自 18.64.211.66 的回复: 字节=32 时间=410ms TTL=245
来自 18.64.211.66 的回复: 字节=32 时间=415ms TTL=245
来自 18.64.211.66 的回复: 字节=32 时间=418ms TTL=245
来自 18.64.211.66 的回复: 字节=32 时间=426ms TTL=245
来自 18.64.211.66 的回复: 字节=32 时间=408ms TTL=245
来自 18.64.211.66 的回复: 字节=32 时间=407ms TTL=245
来自 18.64.211.66 的回复: 字节=32 时间=419ms TTL=245
来自 18.64.211.66 的回复: 字节=32 时间=409ms TTL=245
来自 18.64.211.66 的回复: 字节=32 时间=423ms TTL=245
来自 18.64.211.66 的回复: 字节=32 时间=426ms TTL=245
来自 18.64.211.66 的回复: 字节=32 时间=415ms TTL=245
来自 18.64.211.66 的回复: 字节=32 时间=418ms TTL=245
来自 18.64.211.66 的回复: 字节=32 时间=407ms TTL=245
来自 18.64.211.66 的回复: 字节=32 时间=410ms TTL=245
来自 18.64.211.66 的回复: 字节=32 时间=412ms TTL=245
来自 18.64.211.66 的回复: 字节=32 时间=409ms TTL=245
来自 18.64.211.66 的回复: 字节=32 时间=406ms TTL=245
来自 18.64.211.66 的回复: 字节=32 时间=408ms TTL=245

18.64.211.66 的 Ping 统计信息:
    数据包: 已发送 = 18,已接收 = 18,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
Control-C
PS C:\Users\Thinkpad> ping api.binance.com -n 30

正在 Ping d3h36i1mno13q3.cloudfront.net [18.155.69.202] 具有 32 字节的数据:
来自 18.155.69.202 的回复: 字节=32 时间=263ms TTL=248
来自 18.155.69.202 的回复: 字节=32 时间=255ms TTL=248
来自 18.155.69.202 的回复: 字节=32 时间=265ms TTL=248
来自 18.155.69.202 的回复: 字节=32 时间=257ms TTL=248
来自 18.155.69.202 的回复: 字节=32 时间=256ms TTL=248
来自 18.155.69.202 的回复: 字节=32 时间=253ms TTL=248
来自 18.155.69.202 的回复: 字节=32 时间=253ms TTL=248
来自 18.155.69.202 的回复: 字节=32 时间=257ms TTL=248
来自 18.155.69.202 的回复: 字节=32 时间=256ms TTL=248
来自 18.155.69.202 的回复: 字节=32 时间=254ms TTL=248
来自 18.155.69.202 的回复: 字节=32 时间=273ms TTL=248
来自 18.155.69.202 的回复: 字节=32 时间=297ms TTL=248
来自 18.155.69.202 的回复: 字节=32 时间=310ms TTL=248
来自 18.155.69.202 的回复: 字节=32 时间=311ms TTL=248
来自 18.155.69.202 的回复: 字节=32 时间=253ms TTL=248
来自 18.155.69.202 的回复: 字节=32 时间=253ms TTL=248

18.155.69.202 的 Ping 统计信息:
    数据包: 已发送 = 16,已接收 = 16,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
    最短 = 253ms,最长 = 311ms,平均 = 266ms
Control-C
PS C:\Users\Thinkpad> ping 8.8.8.8 -n 30

正在 Ping 8.8.8.8 具有 32 字节的数据:
来自 8.8.8.8 的回复: 字节=32 时间=253ms TTL=117
来自 8.8.8.8 的回复: 字节=32 时间=256ms TTL=117
来自 8.8.8.8 的回复: 字节=32 时间=253ms TTL=117
来自 8.8.8.8 的回复: 字节=32 时间=257ms TTL=117
来自 8.8.8.8 的回复: 字节=32 时间=262ms TTL=117
来自 8.8.8.8 的回复: 字节=32 时间=253ms TTL=117
来自 8.8.8.8 的回复: 字节=32 时间=259ms TTL=117
来自 8.8.8.8 的回复: 字节=32 时间=254ms TTL=117
来自 8.8.8.8 的回复: 字节=32 时间=254ms TTL=117
来自 8.8.8.8 的回复: 字节=32 时间=254ms TTL=117
来自 8.8.8.8 的回复: 字节=32 时间=258ms TTL=117
来自 8.8.8.8 的回复: 字节=32 时间=253ms TTL=117
来自 8.8.8.8 的回复: 字节=32 时间=257ms TTL=117
来自 8.8.8.8 的回复: 字节=32 时间=254ms TTL=117
来自 8.8.8.8 的回复: 字节=32 时间=253ms TTL=117

8.8.8.8 的 Ping 统计信息:
    数据包: 已发送 = 15,已接收 = 15,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
    最短 = 253ms,最长 = 262ms,平均 = 255ms
Control-C

Binance official website www.binance.com
The shortest is 406ms, the longest is 426ms, the average is 413ms, and the packet is lost.

Binance API API.Binance.com
The shortest is 253ms, the longest is 311ms, the average is 266ms, and the packet is lost.

Public DNS 8.8.8.8
The average delay is 255ms, and the link is smooth and has no packet loss.

Summary: The network path is completely normal, there is no packet loss, and the continuous line, but the transnational delay is seriously high, far below the experience standard of high-quality lines.

  1. Tracert Router Tracking Analysis
PS C:\Users\Thinkpad> tracert www.binance.com

通过最多 30 个跃点跟踪
到 dobbmei4jnjlh.cloudfront.net [13.33.88.84] 的路由:

  1   254 ms   255 ms   260 ms  10.66.66.1 [10.66.66.1]
  2   259 ms   254 ms   253 ms  169.254.169.254
  3   275 ms   285 ms   274 ms  vl199-ds1-j2-r0124.sgp1.constant.com [45.32.97.97]
  4   261 ms   262 ms   253 ms  10.79.0.97 [10.79.0.97]
  5   275 ms   258 ms   257 ms  10.79.1.162 [10.79.1.162]
  6   261 ms   255 ms   280 ms  16509.sgw.equinix.com [27.111.228.87]
  7     *        *        *     请求超时。
  8     *        *        *     请求超时。
  9     *        *        *     请求超时。
 10     *        *        *     请求超时。
 11   252 ms   259 ms   268 ms  server-13-33-88-84.sin2.r.cloudfront.net [13.33.88.84]

跟踪完成。

Through the routing tracking, you can visually see the packet forwarding path, exposing the core problem:
2.1. The first hop delay of the Wireguard gateway starts at 254ms, and the bottleneck is not on the local computer.
2.2. The whole process of ordinary international BGP backbone, there is no CN2 GIA/CMI boutique direct line;
2.3. The routing passes through a large number of intranet relay nodes, and some backbone nodes in the middle section are prohibited from pinging timeouts, and the forwarding path is redundant and deliberately detoured;
2.4. There is no direct connection optimization route, and the innate delay cannot be suppressed, and it is useless to adjust the local settings.

  1. SpeedTest Exit bandwidth speed measurement, open: https://www.speedtest.net/ . The result is shown in Figure 2
SpeedTest Exit bandwidth speed measurement, open: https://www.speedtest.net/ . The result is shown in Figure 2
  • Download: 61.26 Mbps
  • Upload: 41.07 Mbps
  • Speed measurement delay: 304ms ~ 550ms

Key conclusions:
The bandwidth is completely surplus, far enough, and the web page is slow, the market card, and the lag lag in the circle, and has nothing to do with the size of the bandwidth and the level of the machine.

  1. Browser’s real access to somatosensory
    Ordinary static web pages can barely open, but load is slow;
    Visiting market trading platforms such as Binance, the homepage is slow to load slowly, and the switching page is frequently rotated in circles.

3. Deep dismantling: Why is the network very slow, but the network is very slow?
Misunderstanding: near physical distance = fast network speed
The vast majority of novice selection rooms will be intuitive:
Chengdu is close to Singapore in a straight line, which is definitely faster than Los Angeles, USA.

This is the biggest cognitive misunderstanding.
Internet transmission does not look at the physical straight-line distance, but only depends on the backbone route of the operator.

The innate shortcomings of Chengdu Mobile Broadband
Chengdu Mobile does not have a local international export, and all cross-border traffic must first go to Beijing, Shanghai and Guangzhou for unified exports and then go to sea.
Obviously very close, the data packet is transferred around most of the country, and the actual transmission distance has been greatly lengthened.

VULTR Singapore route is inherently limited
To be honest, to say:
There is no CN2 boutique line in all VULTR rooms, all of them are ordinary international BGP lines.
The free time period is barely available, and when the international link of the evening peak is congested, the delay will soar directly.
It is superimposed on the route detour of Chengdu Mobile itself, and the delay is easy to 300-400ms+.

Key conclusion: it’s not that your configuration is not adjusted properly
I have optimized the Windows network, WireGuard parameters, DNS, shunt, and preservation to the best.
It turns out:
Caton high latency has nothing to do with local settings, Wireguard configuration, machine hardware grade, and bandwidth size.

4. Suggestions for landing for self-built Wireguard players

  1. Beginner’s Pit Advice
    Don’t blindly rush to Singapore’s computer room with ‘physical distance’ alone.
    In particular, Chengdu Mobile and ordinary household broadband, blindly choose Vultr Singapore, it is very easy to step on the big pit of high delay.
  2. Three possible options, on demand
    Option 1: Maintain the status quo and make do with self-use
    If you don’t want to toss, don’t want to change service providers, and don’t want to redeploy Wireguard, you can make do with peace of mind.
    Advantages: worry-free migration, configuration does not need to be changed, equipment does not need to be re-adapted;
    Disadvantages: Accept high latency, suitable for ordinary browsing, not suitable for market, transaction, low latency demand scenarios.

Option 2: Leave at VULTR, only change the machine room and not the platform
If you don’t want to change merchants and are afraid of the trouble of reinstalling and deploying, you can migrate the Vultr machine from Singapore to Los Angeles.
The backbone route of Chengdu Mobile is more regular and less detoured, and the delay can be reduced from 400ms to about 200ms, and the stability and fluency have been significantly improved. The original Wireguard just needs to be replaced. IP, the configuration does not need to be changed.

Option 3: Pursuing silky low latency (optimal solution)
If you often visit overseas platforms, watch the market, you need to open the page in seconds, and the K line will not lag:
Give up Vultr directly and choose a VPS merchant with Singapore CN2 GIA boutique line.
Really give full play to the advantages of Singapore’s geography, the domestic delay is stable at 140-180ms, and the evening peak is not congested, delayed, or lost.

5. Written in the final summary

  1. Self-built WireGuard is slow to access the external network, most of which is not a configuration problem, but a double pit for broadband operator routing + VPS lines;
  2. Don’t rely on intuition to choose a computer room, the physical distance is close to the network routing, and Chengdu mobile users should pay special attention;
  3. Vultr is suitable for beginners, simple deployment, loose risk control, but no CN2 dedicated line, not suitable for low-latency rigidity;
  4. If you don’t want to toss, just make do with it. If you want to experience either moving to the Los Angeles computer room, or directly changing the boutique line merchants with CN2.
  5. I myself choose the first option: maintain the status quo and make do with your own use. In the future, when I plan to have free time, I will redeploy it with scheme three.
]]>
https://www.shuijingwanwq.com/en/2026/05/03/10198/feed/ 0
In Laravel 6, when defining a route, use the global config function to access the configuration value https://www.shuijingwanwq.com/en/2023/05/30/12616/ https://www.shuijingwanwq.com/en/2023/05/30/12616/#respond Tue, 30 May 2023 01:06:40 +0000 https://www.shuijingwanwq.com/?p=12616 Post Views: 16

1. In Laravel 6, define the route as follows


Route::get('/static/xxx/{theme_id}/{asset_key}', 'ThemeAssetController@show')->where('asset_key', '.*')->middleware('cache.headers:public;max_age=31536000;etag');


2. Now you need to adjust /static/xxx to get the value from the environment variable, that is, use the global config function to access the configuration value


Route::get('/' . config('filesystems.disks.theme-asset-cdn.root') . '{theme_id}/{asset_key}', 'ThemeAssetController@show')->where('asset_key', '.*')->middleware('cache.headers:public;max_age=31536000;etag');


3. Print output/ / *. config(filesystems.disks.theme-asset-cdn.root) .{theme_id}/{asset_key}, its value is: /static/xxx/{theme_id}/{asset_key} . and the corresponding controller method can be executed. in line with expectations. as shown in Figure 1

打印输出 '/' . config('filesystems.disks.theme-asset-cdn.root') . '{theme_id}/{asset_key}' ,其值为:/static/xxx/{theme_id}/{asset_key} 。且能够执行到对应的控制器方法。符合预期

Figure 1


/static/xxx/{theme_id}/{asset_key}


4. When/ / *. config(filesystems.disks.theme-asset-cdn.root) .{theme_id}/{asset_key}The value is: /static/theme-2.0-test/xxx/{theme_id}/{asset_key}. The corresponding controller method can be executed. in line with expectations. as shown in Figure 2

当 '/' . config('filesystems.disks.theme-asset-cdn.root') . '{theme_id}/{asset_key}' 的值为:/static/theme-2.0-test/xxx/{theme_id}/{asset_key}。能够执行到对应的控制器方法。符合预期

Figure 2

]]>
https://www.shuijingwanwq.com/en/2023/05/30/12616/feed/ 0
In Laravle 6, simulate a route requesting a resource file, and the data is fetched from the database https://www.shuijingwanwq.com/en/2023/05/23/12624/ https://www.shuijingwanwq.com/en/2023/05/23/12624/#respond Tue, 23 May 2023 01:57:36 +0000 https://www.shuijingwanwq.com/?p=12624 Post Views: 13

1. The route of a requesting resource file is as follows: /static/xxx/9915995c-2952-4 90c-8e51-037a0950233c/assets/js/react.f886be.js

2. Since / is included in asset_key. Laravel routing components allow all characters except / . You must explicitly allow / to be part of a placeholder using the WHERE conditional regular expression. Otherwise, the route will fall back. The routes/web.php file is used to define routes to the web interface.


Route::get('/static/xxx/{theme_id}/{asset_key}', 'ModelController@show')->where('asset_key', '.*');


3. Openhttps://regex101.com/, to confirm that the regular expression .* can match assets/js/react.f886be.js. as shown in Figure 1

打开 https://regex101.com/ ,确认正则表达式 .* 可以匹配上 assets/js/react.f886be.js

Figure 1

4. The method of the corresponding controller is implemented as follows. Because it needs to comply with the last-modified specification, use DATE_RFC7231, RFC 7231 format (example: SAT, 30 APR 2016) 17:52:13 GMT). as shown in Figure 2

在对应控制器的方法实现如下,由于需要符合 Last-Modified 规范,使用了 DATE_RFC7231,RFC 7231 格式  (示例:Sat, 30 Apr 2016 17:52:13 GMT)

Figure 2


$model = Model::where('theme_id', '=', $themeId)->where('asset_key', '=', $assetKey)->where('category', '=', Model::CATEGORY_ASSET)->firstOrFail();
return response($model->content, 200)
	->withHeaders([
		'Content-Type' => $model->mime_type,
		'Last-Modified' => date(DATE_RFC7231, strtotime($model->getOriginal('updated_at'))),
	]);


]]>
https://www.shuijingwanwq.com/en/2023/05/23/12624/feed/ 0
In Yii 2.0, based on the RESTful APIs on the desktop application side, the realization of multiplexing and overriding fine-tuning on the mobile application side (1) https://www.shuijingwanwq.com/en/2019/05/11/15250/ https://www.shuijingwanwq.com/en/2019/05/11/15250/#respond Sat, 11 May 2019 08:53:22 +0000 https://www.shuijingwanwq.com/?p=15250 Post Views: 14

1. Open the desktop application terminal, the interface, as shown in Figure 1

打开桌面应用端,界面

Figure 1

2. Interface: my topic selection (get a list of topics), the response structure in postman, as shown in Figure 2

接口:我的选题(获取选题列表),在 Postman 中的响应结构

Figure 2

3. Prototype design on the mobile application side, as shown in Figure 3

在移动应用端的原型设计

Figure 3

4. At this stage: the subsequent iterative development stage, the desktop side and the mobile terminal, in the same interface: my topic selection (obtaining the topic list), there will inevitably be certain differences, so it is decided to plan the corresponding route and the corresponding action respectively. Input files, however, in most interfaces in the current stage/substance iterative development stage, the desktop side is exactly the same as the mobile terminal. Therefore, it is hoped that the implementation in the action can be reused, and the fine-tuning is only covered when there is a difference. Its philosophy can be referenced (separate sites for mobile and desktop):https://developer.mozilla.org/en-US/docs/Web/Guide/Mobile/Separate_sites, openhttp://m.youtube.com/, the display on the desktop and mobile terminals (will automatically judge the request side, if it is the desktop side, it will automatically jump to:https://www.youtube.com/), as shown in Figure 4, Figure 5

打开 http://m.youtube.com/ ,在移动端的显示

Figure 4

打开 http://m.youtube.com/ ,在桌面端与移动端的显示(会自动判断请求端,如果为桌面端,自动跳转至:https://www.youtube.com/ )

Figure 5

5. The configuration of the urlmanager application component, \api\config\urlmanager.php


 yii\web\UrlManager::class,
    'enablePrettyUrl' => true,
    'enableStrictParsing' => true,
    'showScriptName' => false,
    'rules' => [
        [
            'class' => 'yii\rest\UrlRule',
            'controller' => ['v1/user'],
        ],
        /* 选题管理 */
        [
            'class' => 'yii\rest\UrlRule',
            'controller' => ['v1/plan'],
            'only' => ['index', 'create', 'view', 'update', 'delete', 'have', 'wait-review', 'cmc-group', 'edit', 'submit', 'refuse', 'pass', 'return', 'disable', 'enable', 'invite', 'invite-accept'],
            'tokens' => ['{id}' => ''],
            'extraPatterns' => [
                'GET have' => 'have',
                'GET wait-review' => 'wait-review',
                'GET cmc-group/{id}' => 'cmc-group',
                'GET edit/{id}' => 'edit',
                'PUT submit/{id}' => 'submit',
                'PUT refuse/{id}' => 'refuse',
                'PUT pass/{id}' => 'pass',
                'PUT return/{id}' => 'return',
                'PUT disable/{id}' => 'disable',
                'PUT enable/{id}' => 'enable',
                'POST invite/{id}' => 'invite',
                'PUT invite-accept/{id}' => 'invite-accept',
            ],
        ],
    ],
];



6. Controller class: \API\Controllers\planController.php, declared through the actions() method


 'api\rests\plan\Serializer',
        'collectionEnvelope' => 'items',
    ];

    /**
     * @inheritdoc
     */
    public function actions()
    {
        $actions = parent::actions();
        // 禁用"options"动作
        unset($actions['options']);
        $actions['index']['class'] = 'api\rests\plan\IndexAction';
        $actions['create']['class'] = 'api\rests\plan\CreateAction';
        $actions['view']['class'] = 'api\rests\plan\ViewAction';
        $actions['update']['class'] = 'api\rests\plan\UpdateAction';
        $actions['delete']['class'] = 'api\rests\plan\DeleteAction';
        $actions['have'] = [
            'class' => 'api\rests\plan\HaveAction',
            'modelClass' => $this->modelClass,
            'checkAccess' => [$this, 'checkAccess'],
        ];
        $actions['wait-review'] = [
            'class' => 'api\rests\plan\WaitReviewAction',
            'modelClass' => $this->modelClass,
            'checkAccess' => [$this, 'checkAccess'],
        ];
        $actions['cmc-group'] = [
            'class' => 'api\rests\plan\CmcGroupAction',
            'modelClass' => $this->modelClass,
            'checkAccess' => [$this, 'checkAccess'],
        ];
        $actions['edit'] = [
            'class' => 'api\rests\plan\EditAction',
            'modelClass' => $this->modelClass,
            'checkAccess' => [$this, 'checkAccess'],
        ];
        $actions['submit'] = [
            'class' => 'api\rests\plan\SubmitAction',
            'modelClass' => $this->modelClass,
            'checkAccess' => [$this, 'checkAccess'],
        ];
        $actions['refuse'] = [
            'class' => 'api\rests\plan\RefuseAction',
            'modelClass' => $this->modelClass,
            'checkAccess' => [$this, 'checkAccess'],
        ];
        $actions['pass'] = [
            'class' => 'api\rests\plan\PassAction',
            'modelClass' => $this->modelClass,
            'checkAccess' => [$this, 'checkAccess'],
        ];
        $actions['return'] = [
            'class' => 'api\rests\plan\ReturnAction',
            'modelClass' => $this->modelClass,
            'checkAccess' => [$this, 'checkAccess'],
        ];
        $actions['disable'] = [
            'class' => 'api\rests\plan\DisableAction',
            'modelClass' => $this->modelClass,
            'checkAccess' => [$this, 'checkAccess'],
        ];
        $actions['enable'] = [
            'class' => 'api\rests\plan\EnableAction',
            'modelClass' => $this->modelClass,
            'checkAccess' => [$this, 'checkAccess'],
        ];
        $actions['invite'] = [
            'class' => 'api\rests\plan\InviteAction',
            'modelClass' => $this->modelClass,
            'checkAccess' => [$this, 'checkAccess'],
        ];
        $actions['invite-accept'] = [
            'class' => 'api\rests\plan\InviteAcceptAction',
            'modelClass' => $this->modelClass,
            'checkAccess' => [$this, 'checkAccess'],
        ];
        return $actions;
    }
}



7. Use the module to isolate the code of different versions, \API\modules\v1\Controllers\PlanController.php



8. Action file: \API\RESTS\PLAN\HaveAction.php Inherited to \yii\rest\ActiveController Default provided action: \yii\rest\indexAction



 * @since 1.0
 */
class HaveAction extends \yii\rest\IndexAction
{
    public $dataFilter = [
        'class' => 'yii\data\ActiveDataFilter',
        'searchModel' => 'api\models\PlanSearch',
        'attributeMap' => [
            'created_at' => '{{%plan}}.[[created_at]]',
            'status' => '{{%plan}}.[[status]]',
            'title' => '{{%plan}}.[[title]]',
        ],
    ];

    /**
     * Prepares the data provider that should return the requested collection of the models.
     * @return ActiveDataProvider
     * @throws InvalidConfigException if a registered parser does not implement the [[RequestParserInterface]].
     * @throws UnprocessableEntityHttpException
     */
    protected function prepareDataProvider()
    {
        $requestParams = Yii::$app->getRequest()->getBodyParams();
        if (empty($requestParams)) {
            $requestParams = Yii::$app->getRequest()->getQueryParams();
        }
        $filter = null;
        if ($this->dataFilter !== null) {
            $this->dataFilter = Yii::createObject($this->dataFilter);
            if ($this->dataFilter->load($requestParams)) {
                $filter = $this->dataFilter->build();
                if ($filter === false) {
                    $firstError = '';
                    foreach ($this->dataFilter->getFirstErrors() as $message) {
                        $firstError = $message;
                        break;
                    }
                    throw new UnprocessableEntityHttpException(Yii::t('error', Yii::t('error', Yii::t('error', '224003'), ['first_error' => $firstError])), 224003);
                }
            }
        }

        if ($this->prepareDataProvider !== null) {
            return call_user_func($this->prepareDataProvider, $this, $filter);
        }

        // 当前用户的身份实例,未认证用户则为 Null
        /* @var $identity RedisCmcConsoleUser */
        $identity = Yii::$app->user->identity;

        /* @var $modelClass Plan */
        $modelClass = $this->modelClass;

        /* @var $haveQuery PlanQuery */
        // 获取查询对象(我的选题(获取选题列表))
        $haveQuery = $modelClass::getHaveQuery($identity);

        $query = $haveQuery->orderBy([$modelClass::tableName() . '.id' => SORT_DESC]);

        if (!empty($filter)) {
            $query->andFilterWhere($filter);
        }

        return Yii::createObject([
            'class' => ActiveDataProvider::className(),
            'query' => $query,
            'pagination' => [
                'params' => $requestParams,
            ],
            'sort' => [
                'params' => $requestParams,
            ],
        ]);
    }
}



9. Due to the same interface, its business logic is basically the same, and the implementation of business logic exists in the directory: \common\models, \co Mmon\logics, \common\services, \api\models, \api\services. Therefore, there is no need to distinguish based on modules, it can be implemented based on the subdirectories of the controller. Create a new mobile directory: \api\controllers\mobile, copy \api\controllers\plancontroller.php to \API\Controllers\Mobile\PlanController.php

10. The configuration of the urlmanager application component, \api\config\urlmanager.php, added: mobile terminal – topic selection


        /* 移动端 */
        // 移动端 - 选题
        [
            'class' => 'yii\rest\UrlRule',
            'controller' => ['v1/mobile/plan'],
            'only' => ['index', 'create', 'view', 'update', 'delete', 'have', 'wait-review', 'cmc-group', 'edit', 'submit', 'refuse', 'pass', 'return', 'disable', 'enable', 'invite', 'invite-accept'],
            'tokens' => ['{id}' => ''],
            'extraPatterns' => [
                'GET have' => 'have',
                'GET wait-review' => 'wait-review',
                'GET cmc-group/{id}' => 'cmc-group',
                'GET edit/{id}' => 'edit',
                'PUT submit/{id}' => 'submit',
                'PUT refuse/{id}' => 'refuse',
                'PUT pass/{id}' => 'pass',
                'PUT return/{id}' => 'return',
                'PUT disable/{id}' => 'disable',
                'PUT enable/{id}' => 'enable',
                'POST invite/{id}' => 'invite',
                'PUT invite-accept/{id}' => 'invite-accept',
            ],
        ],


11. Controller class: \API\Controllers\Mobile\PlanController.php, inherited to:\API\Controllers\PlanController, declare through the actions() method, overwrite the method class file


 'api\rests\mobile\plan\Serializer',
        'collectionEnvelope' => 'items',
    ];

    /**
     * @inheritdoc
     */
    public function actions()
    {
        $actions = parent::actions();
        $actions['index']['class'] = 'api\rests\mobile\plan\IndexAction';
        $actions['create']['class'] = 'api\rests\mobile\plan\CreateAction';
        $actions['view']['class'] = 'api\rests\mobile\plan\ViewAction';
        $actions['update']['class'] = 'api\rests\mobile\plan\UpdateAction';
        $actions['delete']['class'] = 'api\rests\mobile\plan\DeleteAction';
        $actions['have']['class'] = 'api\rests\mobile\plan\HaveAction';
        $actions['wait-review']['class'] = 'api\rests\mobile\plan\WaitReviewAction';
        $actions['cmc-group']['class'] = 'api\rests\mobile\plan\CmcGroupAction';
        $actions['edit']['class'] = 'api\rests\mobile\plan\EditAction';
        $actions['submit']['class'] = 'api\rests\mobile\plan\SubmitAction';
        $actions['refuse']['class'] = 'api\rests\mobile\plan\RefuseAction';
        $actions['pass']['class'] = 'api\rests\mobile\plan\PassAction';
        $actions['return']['class'] = 'api\rests\mobile\plan\ReturnAction';
        $actions['disable']['class'] = 'api\rests\mobile\plan\DisableAction';
        $actions['enable']['class'] = 'api\rests\mobile\plan\EnableAction';
        $actions['invite']['class'] = 'api\rests\mobile\plan\InviteAction';
        $actions['invite-accept']['class'] = 'api\rests\mobile\plan\InviteAcceptAction';
        return $actions;
    }
}



12. Use the module to isolate the code of different versions, copy \api\modules\v1\controllers\plancontroller.php to \API\modules\v1\Controllers\Mobile\PlanController.php, which inherits to \API\Controllers\Mobile\PlanController



13. Copy \API\RESTS\PLAN to \API\RESTs\Mobile\Plan, and replace the namespace in batches, as shown in Figure 6

复制 \api\rests\plan 至 \api\rests\mobile\plan,批量替换命名空间

Figure 6

14. Edit the action file:\api\rests\mobile\plan\haveaction.php, inherit to \API\RESTS\PLAN\HaveAction, since there is no difference between the mobile terminal and the desktop side of this interface, the run() method in the file can be deleted



15. Convert the resource object to an array, edit the data serialization file: \api\rests\mobile\plan\serializer.php, inherit to \API\RESTS\PLAN\Serializer, since there is no difference between the mobile terminal and the desktop side of this interface, so the SerializeDataProvider() method in the file can be deleted



16. Open the desktop interface in Postman, as shown in Figure 7

在 Postman 中打开桌面端接口

Figure 7

17. Open the mobile terminal interface in Postman, as shown in Figure 8

在 Postman 中打开移动端接口

8

18. If there is a difference between the mobile terminal and the desktop side of this interface, the run() method can be overwritten and adjusted. In the follow-up, we will try to extract some reusable codes in the run() method and implement them as a method (placed in the file: \API\RESTS\PLAN\HaveAction.php).

 

]]>
https://www.shuijingwanwq.com/en/2019/05/11/15250/feed/ 0
In Yii 2’s RESTful service, get url/, response 404 solution (response 200) https://www.shuijingwanwq.com/en/2017/08/29/16145/ https://www.shuijingwanwq.com/en/2017/08/29/16145/#respond Tue, 29 Aug 2017 09:37:54 +0000 https://www.shuijingwanwq.com/?p=16145 Post Views: 3

1. In APM monitoring, due to Alibaba Cloud’s get URL/request, a large number of 404 responses are caused, which has a certain interference to the operation and maintenance work, as shown in Figure 1

在 APM 监控中,由于阿里云的 GET URL / 请求,导致大量的404响应,对于运维的工作有一定的干扰

Figure 1

2. Request in Postman:http://api.kaiqiu_shujujiexi_api.dev/, response 404, as shown in Figure 2

在 Postman 中请求:http://api.kaiqiu_shujujiexi_api.dev/ ,响应404

Figure 2

3. When the request is resolved to an empty route, the so-called default route will be used. why no route tosite/index, the reason is that strict request resolution is enabled in the configuration file, as shown in Figure 3
EnableStrictParsing=> true,

If strict parsing is enabled, the URL of the incoming request must match at least one rule to be considered a valid request, otherwise a yii\web\NotFoundHttpException will be thrown. If strict parsing is disabled, the path information portion of the URL will be considered the route of the request when no rules match the requested URL.

当请求被解析为空路由时,将使用所谓的默认路由。为何没有路由至 'site/index',原因在于配置文件中启用了严格请求解析

Figure 3

4. Add one to the URL rule, as shown in Figure 4

在 URL 规则中添加一条

Figure 4

5. Request in Postman:http://api.kaiqiu_shujujiexi_api.dev/, response 200, as shown in Figure 5

在 Postman 中请求:http://api.kaiqiu_shujujiexi_api.dev/ ,响应200

Figure 5

6,site/indexcode in Figure 6

'site/index' 中的代码

Figure 6

 

]]>
https://www.shuijingwanwq.com/en/2017/08/29/16145/feed/ 0