The code address of this article is github.

Functional specifications

The default private repository pub_server service program only outputs a success log in the command line after the package is successfully uploaded, without the necessary message notification, and the developer does not know that the package is successfully published. Since wechat is widely used at work and group robots can conveniently push messages in the work group, we want to push the uploaded messages to the group through group robots.

For the access method of enterprise wechat group robots, please refer to the configuration description of group robots.

The code analysis

Related classes

Before modifying the code, I took a complete look at the implementation code of pub_server.

Dart file ShelfPubServer class, which is responsible for the specific processing logic of each server interface. The request and feedback messages for each interface can be obtained in the requestHandler method. Uploading the package bag involves/API/packages/versions/newUpload and/API/packages/versions/newUploadFinish two interfaces, the first interface of the duties of the said specific upload logic, The second interface just completes the upload operation. After the first interface is successfully processed, a 302 request is returned, allowing the client to request the second interface directly.

The cow_Repository. dart file CopyAndWriteRepository class, which is the core of the service and ultimately handles all the processing of the ShelfPubServer class. The FileRepository class, which holds the file_repository.dart file, is responsible for the actual upload.

Theoretically, we can monitor the successful message of package uploading in the relevant codes of ShelfPubServer class, CopyAndWriteRepository class and FileRepository class, and send message request to the group robot of enterprise wechat at the relevant code location.

The initial plan

I originally planned in ShelfPubServer _finishUploadSimple method of a class, / API/packages/versions/newUploadFinish interface returns Successfully uploaded package. Messages are sent directly to the robot. But later found two problems: first, in the/API/packages/versions/newUploadFinish does not carry the request of the interface parameters upload information package bag, so can’t send relevant notification text; Second, inserting the code to send messages to swarm robots in the ShelfPubServer class will pollute the original logical code and cause unnecessary code coupling. If we need to add email notifications and pin notifications later, do we need to add more code?

One of the first questions you can change/API/packages/versions/newUpload interface method returns a message, but on the original logic code changes, do not use temporarily; Thinking about the second problem, I was ready to implement a request processing interceptor myself to decouple the code and found this code:

  // Start an HTTP service
  return shelf_io.serve(
      const Pipeline()
          .addMiddleware(logRequests()) // Log middleware
          .addHandler(server.requestHandler), // Request handler
      host,
      port);
Copy the code

This is the code to start HTTP services based on the shelf framework, where addMiddleware(logRequests() is middleware that adds logging output to interface requests and feedback. I did not write the back-end interface, but after looking at the code of Pipeline, I think it is just possible to use middleware to achieve this function.

implementation

Add a generic interceptor middleware

Dart added interceptor_middleware.dart:

Middleware interceptorMiddleware({Function beforeHandler, Function successHandler, Function errorHandler})
Copy the code

The middleware enables business code to execute its own logic before, after, and after each request is processed.

Add enterprise wechat group robot middleware

New robot middleware qywx_robot_middleware.dart:

Middleware qywxRobotMiddleware(String qywxkey, {MsgBuilder msgBuilder})
Copy the code

This middleware encapsulates [interceptorMiddleware], in which QyWxKey is the key of enterprise wechat open platform, and msgBuilder is the message body builder for group robots to send messages. For details, see the message type and data format in the configuration instructions of group robots.

Middleware intercepted in the implementation of the code/API/packages/versions/newUpload interface request, when the interface treatment success, and statusCode to 302, the group of robot related API calls.

This middleware provides a default message body constructor:

Map defaultMsgBuilder(PackageVersion packageVersion) {
  return {
    'msgtype': 'text'.'text': {
      'content': 'Oh my God! Flutter Package${packageVersion.packageName}The new v${packageVersion.versionString}It's so nice! Use it! Use it! Use it! '.'mentioned_list': ['@all']}}; }Copy the code

It is optional to add enterprise wechat group robot middleware

  var pipeline = Pipeline();
  if(qywxkey! =null && qywxkey.isNotEmpty) {
    pipeline = pipeline.addMiddleware(qywxRobotMiddleware(qywxkey)); // Enterprise wechat robot middleware
  }
  pipeline = pipeline.addMiddleware(logRequests()); // Log middleware
  // Start an HTTP service
  return shelf_io.serve(
      pipeline.addHandler(server.requestHandler), // Request handler
      host,
      port);
Copy the code

When the HTTP service is started, the robot middleware is loaded when qywxkey is present, otherwise it is not. Where qywxkey is passed as a command line argument:

ArgParser argsParser() {
  var parser = ArgParser();

  // Set the supported parameters and default values for the parameter parser
  parser.addOption('directory',
      abbr: 'd', defaultsTo: 'pub_server-repository-data');

  parser.addOption('host', abbr: 'h', defaultsTo: 'localhost');

  parser.addOption('port', abbr: 'p', defaultsTo: '8080');
  parser.addOption('qywxkey', abbr: 'q', defaultsTo: ' ');
  parser.addFlag('standalone', abbr: 's', defaultsTo: false);
  return parser;
}
Copy the code

Full code address

github

Method of use

CD ~/pub_server dart example/example.dart -d ~/package-db -h 192.168.1.2 -p 8090 -q xxxx-xxxx-qywxkeyCopy the code

When starting the service, you only need to pass qywxkey in addition to the IP address and interface.

End result:

Details to be optimized

  • qywxRobotMiddlewareWhat the middleware code intercepts is/api/packages/versions/newUploadInterface, this interface only upload operation, and did not upload successfully, so theoretically still want to intercept/api/packages/versions/newUploadFinishInterface;
  • /api/packages/versions/newUploadThe interface returns only the name and version of the package, with no changes to that version. However, update instructions exist in the official guide of the PackageCHANGELOG.mdFile, so to read the version update description, you need to parse the MarkDown file later;