Extension:Math/RESTBase

From Linux Web Expert

Configure Restbase to work with the Math extension

To install mathoid and restbase to work with the math extension the following steps are required:

Mathoid

npm i mathoid
cd node_modules/mathoid

edit config.yaml as follows

# Number of worker processes to spawn.
# Set to 0 to run everything in a single process without clustering.
# Use 'ncpu' to run as many workers as there are CPU units
num_workers: ncpu

# Log error messages and gracefully restart a worker if v8 reports that it
# uses more heap (note: not RSS) than this many mb.
worker_heap_limit_mb: 500

# Logger info
logging:
  level: warn

# Statsd metrics reporter
metrics:
  type: log
  #host: localhost
  #port: 8125

services:
  - name: mathoid
    # a relative path or the name of an npm package, if different from name
    module: ./app.js
    # optionally, a version constraint of the npm package
    # version: ^0.4.0
    # per-service config
    conf:
      port: 10042
      # interface: localhost # uncomment to only listen on localhost
      # more per-service config settings
      svg: true
      img: true
      png: true
      texvcinfo: true
      speech: true
      speech_on: false
      chem: true
      no_check: true

run mathoid as a screen session

screen
node server.js -c config.yaml

testing mathoid

Now the following test

curl -d 'q=E=mc^2' localhost:10042/mml

should return

<math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
  <semantics>
    <mrow>
      <mi>E</mi>
      <mo>=</mo>
      <mi>m</mi>
      <msup>
        <mi>c</mi>
        <mn>2</mn>
      </msup>
    </mrow>
    <annotation encoding="application/x-tex">E=mc^2</annotation>
  </semantics>
</math>

RESTBase

npm i restbase
cd node_modules/restbase

edit config.yaml as follows

paths:
  /{api:v1}:
    x-modules:
        # swagger options, overriding the shared ones from the merged specs (?)
      - spec:
          info:
            version: 1.0.0-beta
            title: Formulasearchengine REST API
            description: >
                This API aims to provide a preview of new features reagarding
                Math rendering and search, supposed to be integrated to
                the [wikimedia restbase api](https://wikimedia.org/api/rest_v1/?doc).

                ### High-volume access
                  - Don't perform more than 500 requests/s to this API.
                  - Set a unique `User-Agent` header that allows us to contact you
                    quickly. Email addresses or URLs of contact pages work well.

            termsOfService: https://wikimediafoundation.org/wiki/Terms_of_Use
            contact:
              name: the Wikimedia Services team
              url: http://mediawiki.org/wiki/RESTBase
            license:
              name: Apache2
              url: http://www.apache.org/licenses/LICENSE-2.0

          securityDefinitions: &wp/content-security/1.0.0
            mediawiki_auth:
              description: Checks permissions using MW api
              type: apiKey
              in: header
              name: cookie
              x-internal-request-whitelist:
                - /http:\/\/[a-zA-Z0-9\.]+\/w\/api\.php/
          # Override the base path for host-based (proxied) requests. In our case,
          # we proxy https://{domain}/api/rest_v1/ to the API.
          x-host-basePath: /api/rest_v1
          x-route-filters:
            - path: ./lib/normalize_title_filter.js
              options:
                redirect_cache_control: '{{options.purged_cache_control}}'
          paths:
            /media:
              x-modules:
                - path: v1/mathoid.yaml
                  options: '{{options.mathoid}}'
            /testing:
              x-modules:
                - path: ../mathpipe.yaml
                 # options: '{{options.mathoid}}'
        options: '{{options}}'

  /{api:sys}:
    x-modules:
      - spec:
          paths:
            /mathoid:
              x-modules:
                - path: sys/mathoid.js
                  options: '{{options.mathoid}}'
            /table:
              x-modules:
                - path: sys/table.js
                  options:
                    conf: '{{options.table}}'
            /key_value:
              x-modules:
                - path: sys/key_value.js
            /key_rev_value:
              x-modules:
                - path: sys/key_rev_value.js
            /key_rev_latest_value:
              x-modules:
                - path: sys/key_rev_latest_value.js
            /post_data: &sys_post_data
              x-modules:
                - path: sys/post_data.js
            /events:
              x-modules:
                - path: sys/events.js
                  options: '{{options.events}}'
        options: '{{options}}'

run restbase as a screen session

screen
node server.js -c config.yaml

testing restbase

Navigate to http://localhost:8081/wikimedia.org/v1/?doc you should be able to enter a texvc formula to the check command POST endpoing i.e. /media/math/check/{type} (See screenshot 1)[1] In the response headers you should find something like

"x-resource-location": "4c0004393a88f350a93bcef62106d556c7fc827b"

If you copy the value 4c0004393a88f350a93bcef62106d556c7fc827b and paste it to the GET endpoint /media/math/render/{format}/{hash} as value you should be able to see the PNG image if you select that as an output format. (See screenshot 2)[2]

Configuration Example for arbitrary domain in RESTBase setup

If you want to use domain other than wikimedia.org, you can follow below example;

  • mathoid/config.yaml
# Number of worker processes to spawn.
# Set to 0 to run everything in a single process without clustering.
# Use 'ncpu' to run as many workers as there are CPU units
num_workers: 0

# Log error messages and gracefully restart a worker if v8 reports that it
# uses more heap (note: not RSS) than this many mb.
worker_heap_limit_mb: 250

# Logger info
logging:
  level: trace
#  streams:
#  # Use gelf-stream -> logstash
#  - type: gelf
#    host: logstash1003.eqiad.wmnet
#    port: 12201

# Statsd metrics reporter
metrics:
  #type: log
  #host: localhost
  #port: 8125

services:
  - name: mathoid
    # a relative path or the name of an npm package, if different from name
    module: ./app.js
    # optionally, a version constraint of the npm package
    # version: ^0.4.0
    # per-service config
    conf:
      port: 10044
      # interface: localhost # uncomment to only listen on localhost
      # more per-service config settings
      # the location of the spec, defaults to spec.yaml if not specified
      # spec: ./spec.template.yaml
      # allow cross-domain requests to the API (default '*')
      #cors: '*'
      # to disable use:
      # cors: false
      # to restrict to a particular domain, use:
      # cors: restricted.domain.org
      # content for the CSP headers
      # csp: false  # uncomment this line to disable sending them
      # URL of the outbound proxy to use (complete with protocol)
      # proxy: http://my.proxy.org:8080
      # the list of domains for which not to use the proxy defined above
      # no_proxy_list:
      #   - domain1.com
      #   - domain2.org
      # the list of incoming request headers that can be logged; if left empty,
      # the following headers are allowed: cache-control, content-length,
      # content-type, if-match, user-agent, x-request-id
      # log_header_whitelist:
      #   - cache-control
      #   - content-length
      #   - content-type
      #   - if-match
      #   - user-agent
      #   - x-request-id
      # list of enabled renders
      svg: true
      img: true
      png: true #new feature
      speech: true #new feature
      texvcinfo: true
      speech_on: true
      no_check: false
      dpi: 180
      svgo: false
      # the user agent to use when issuing requests
      # user_agent: service-template-node
      # the template used for contacting the MW API
      #mwapi_req:
      #  method: post
      #  uri: https://{{domain}}/w/api.php
      #  headers:
      #    user-agent: '{{user-agent}}'
      #  body: '{{ default(request.query, {}) }}'
      # the template used for contacting RESTBase
      #restbase_req:
      #  method: '{{request.method}}'
      #  uri: https://{{domain}}/api/rest_v1/{+path}
      #  query: '{{ default(request.query, {}) }}'
      #  headers: '{{request.headers}}'
      #  body: '{{request.body}}'
  • restbase/config.yaml
services:
  - name: restbase
    module: hyperswitch
    conf:
      port: 7231
      salt: secret
      default_page_size: 125
      user_agent: RESTBase
      ui_name: RESTBase
      ui_url: https://www.mediawiki.org/wiki/RESTBase
      ui_title: RESTBase docs
      spec:
        x-request-filters:
          - path: lib/security_response_header_filter.js
        x-sub-request-filters:
          - type: default
            name: http
            options:
            allow:
              - pattern: http://localhost/api.php
                forward_headers: true
              - pattern: http://localhost:8000
                forward_headers: true
              - pattern: http://localhost:10044
                forward_headers: true
              - pattern: /^https?:\/\//
        paths:
          /{domain:localhost}: &arbitary_domain
            x-modules:
              - path: projects/MR.yaml
                options:
                  action:
                    # XXX Check API URL!
                    apiUriTemplate: http://localhost/api.php
                    # XXX Check the base RESTBase URI
                    baseUriTemplate: "{{'http://localhost:7231/{domain}/v1'}}"
                  parsoid:
                    # XXX Check Parsoid URL!
                    host: http://localhost:8000
                  mathoid:
                    # XXX Check Mathoid URL!
                    host: http://localhost:10044
                  table:
                    backend: sqlite
                    dbname: db.sqlite3
                    pool_idle_timeout: 20000
                    retry_delay: 250
                    retry_limit: 10
                    show_sql: false
          /{domain:your.some.domain}: *arbitary_domain

# Finally, a standard service-runner config.
info:
  name: restbase

logging:
  name: restbase
  level: info
  • restbase/project/MR.yaml
# will work with Mathoid on any {domain}
paths:
  /{api:v1}:
    x-modules:
        # swagger options, overriding the shared ones from the merged specs (?)
      - spec:
          info:
            version: 1.0.0
            title: Wikimedia REST API
            description: Welcome to your RESTBase API.
          #securityDefinitions: &wp/content-security/1.0.0
          #  mediawiki_auth:
          #    description: Checks permissions using MW api
          #    type: apiKey
          #    in: header
          #    name: cookie
          #    x-internal-request-whitelist:
          #      - /http:\/\/[a-zA-Z0-9\.]+\/w\/api\.php/
          # Override the base path for host-based (proxied) requests. In our case,
          # we proxy https://{domain}/api/rest_v1/ to the API.
          #x-host-basePath: /api/rest_v1
          x-route-filters:
            - path: ./lib/normalize_title_filter.js
              options:
                redirect_cache_control: '{{options.purged_cache_control}}'
          paths:
            /media:
              x-modules:
                - path: v1/mathoid.yaml
                  options: '{{options.mathoid}}'
            #/testing:
            #  x-modules:
            #    - path: ../mathpipe.yaml
                 # options: '{{options.mathoid}}'
            /page:
              x-modules:
                - path: v1/content.yaml
                  options:
                    purged_cache_control: '{{options.purged_cache_control}}'
                - path: v1/common_schemas.yaml # Doesn't really matter where to mount it.
            /transform:
              x-modules:
                - path: v1/transform.yaml
        options: '{{options}}'

  /{api:sys}:
    x-modules:
      - spec:
          paths:
            /mathoid:
              x-modules:
                - path: sys/mathoid.js
                  options: '{{options.mathoid}}'
            /table:
              x-modules:
                - path: sys/table.js
                  options:
                    conf: '{{options.table}}'
            /key_value:
              x-modules:
                - path: sys/key_value.js
            /key_rev_value:
              x-modules:
                - path: sys/key_rev_value.js
            /key_rev_latest_value:
              x-modules:
                - path: sys/key_rev_latest_value.js
            /post_data: &sys_post_data
              x-modules:
                - path: sys/post_data.js
            /events:
              x-modules:
                - path: sys/events.js
                  options: '{{options.events}}'
            /page_revisions:
              x-modules:
                - path: sys/page_revisions.js
            /action:
              x-modules:
                - path: sys/action.js
                  options: '{{options.action}}'
            /page_save:
              x-modules:
                - path: sys/page_save.js
            /parsoid:
              x-modules:
                - path: sys/parsoid.js
                  options:
                    parsoidHost: '{{options.parsoid.host}}'
                    response_cache_control: '{{options.purged_cache_control}}'
        options: '{{options}}'
  • restbase/v1/mathoid.yaml
# Mathoid - math formula rendering service :simply replaced /wikimedia.org/sys to /{domain}/sys
tags:
  - name: Math
    description: formula rendering
paths:
  /math/check/{type}:
    post:
      tags: ['Math']
      summary: Check and normalize a TeX formula.
      description: |
        Checks the supplied TeX formula for correctness and returns the
        normalised formula representation as well as information about
        identifiers. Available types are tex and inline-tex. The response
        contains the `x-resource-location` header which can be used to retrieve
        the render of the checked formula in one of the supported rendering
        formats. Just append the value of the header to `/media/math/{format}/`
        and perform a GET request against that URL.

        Stability: [stable](https://www.mediawiki.org/wiki/API_versioning#Stable).
      produces:
        - application/json
      parameters:
        - name: type
          in: path
          description: The input type of the given formula; can be tex or inline-tex
          type: string
          required: true
          enum:
            - tex
            - inline-tex
            - chem
        - name: q
          in: formData
          description: The formula to check
          type: string
          required: true
      responses:
        '200':
          description: Information about the checked formula
        '400':
          description: Invalid type
          schema:
            $ref: '#/definitions/problem'
        default:
          description: Error
          schema:
            $ref: '#/definitions/problem'
      x-monitor: true
      x-amples:
        - title: Mathoid - check test formula
          request:
            params:
              domain: wikimedia.org
              type: tex
            body:
              q: E=mc^{2}
          response:
            status: 200
            headers:
              content-type: /^application\/json/
              x-resource-location: /.+/
              cache-control: 'no-cache'
            body:
              success: true
              checked: /.+/
      x-request-handler:
        - get_from_sys:
            request:
              method: post
              uri: /{domain}/sys/mathoid/check/{type}
              headers: '{{ request.headers }}'
              body: '{{ request.body }}'

  /math/formula/{hash}:
    get:
      tags: ['Math']
      summary: Get a previously-stored formula
      description: |
        Returns the previously-stored formula via `/media/math/check/{type}` for
        the given hash.

        Stability: [stable](https://www.mediawiki.org/wiki/API_versioning#Stable).
      produces:
        - application/json
      parameters:
        - name: hash
          in: path
          description: The hash string of the previous POST data
          type: string
          required: true
          minLength: 1
      responses:
        '200':
          description: Information about the checked formula
        '404':
          description: Data for the given hash cannot be found
          schema:
            $ref: '#/definitions/problem'
        default:
          description: Error
          schema:
            $ref: '#/definitions/problem'
      x-monitor: false
      x-request-handler:
        - get_from_sys:
            request:
              method: get
              uri: /{domain}/sys/mathoid/formula/{hash}
              headers: '{{ request.headers }}'

  /math/render/{format}/{hash}:
    get:
      tags: ['Math']
      summary: Get rendered formula in the given format.
      description: |
        Given a request hash, renders a TeX formula into its mathematic
        representation in the given format. When a request is issued to the
        `/media/math/check/{format}` POST endpoint, the response contains the
        `x-resource-location` header denoting the hash ID of the POST data. Once
        obtained, this endpoint has to be used to obtain the actual render.

        Stability: [stable](https://www.mediawiki.org/wiki/API_versioning#Stable).
      produces:
        - image/svg+xml
        - application/mathml+xml
        - image/png
      parameters:
        - name: format
          in: path
          description: The output format; can be svg or mml
          type: string
          required: true
          enum:
            - svg
            - mml
            - png
        - name: hash
          in: path
          description: The hash string of the previous POST data
          type: string
          required: true
          minLength: 1
      responses:
        '200':
          description: The rendered formula
        '404':
          description: Unknown format or hash ID
          schema:
            $ref: '#/definitions/problem'
        default:
          description: Error
          schema:
            $ref: '#/definitions/problem'
      x-monitor: false
      x-setup-handler:
        - init_svg:
            uri: /{domain}/sys/key_value/mathoid.svg
            body:
              keyType: string
              valueType: string
        - init_mml:
            uri: /{domain}/sys/key_value/mathoid.mml
            body:
              keyType: string
              valueType: string
        - init_png:
            uri: /{domain}/sys/key_value/mathoid.png
            body:
              keyType: string
              valueType: blob
      x-request-handler:
        - check_storage:
            request:
              method: get
              uri: /{domain}/sys/key_value/mathoid.{$.request.params.format}/{$.request.params.hash}
              headers:
                cache-control: '{{ cache-control }}'
            catch:
              status: 404
            return_if:
              status: '2xx'
            return:
              status: 200
              headers: "{{ merge({ 'cache-control': options.cache-control }, check_storage.headers) }}"
              body: '{{ check_storage.body }}'
        - postdata:
            request:
              uri: /{domain}/sys/mathoid/formula/{request.params.hash}
        - mathoid:
            request:
              method: post
              uri: /{domain}/sys/mathoid/render/{request.params.format}
              headers:
                content-type: application/json
                x-resource-location: '{{ request.params.hash }}'
              body: '{{postdata.body}}'
  • Apache proxy config : /etc/httpd/conf.d/restbase.conf
#
# Restbase
#

<VirtualHost *:80>
          ProxyPreserveHost On

          ProxyPass /your.some.domain/ http://localhost:7231/your.some.domain/
          ProxyPassReverse /your.some.domain/ http://localhost:7231/your.some.domain/

          ProxyPass /localhost/ http://localhost:7231/localhost/
          ProxyPassReverse /localhost/ http://localhost:7231/localhost/

          # MediaWiki is located here:
          DocumentRoot /var/www/html
 </VirtualHost>

you can test the APIs at http://your.some.domain/your.some.domain/v1/

setup apache proxy

To load the images from the same location where the main wiki site is hosted a simple apache proxy can be used. Enable apache mod proxy ... and then add a config file along the lines of this file

cat /etc/apache2/sites-available/restbase.conf
<VirtualHost *:80>
    ServerName  restbase.formulasearchengine.com
    ServerAlias api.formulasearchengine.com png.formulasearchengine.com
    ServerAdmin wiki@physikerwelt.de
    ProxyPreserveHost On
    ProxyPass /v1/ http://localhost:8081/wikimedia.org/v1/
    ProxyPass /wikimedia.org/v1/ http://localhost:8081/wikimedia.org/v1/
</VirtualHost>
a2ensite restbase.conf

You can use letsencrypt to also generate a HTTPS version for that site.

Helpful commands to check the state of the database

Clean cache

run cqlsh

use "local_group_default_T_mathoid_svg";
truncate data;
truncate meta;
use "local_group_default_T_mathoid_mml";
truncate data;
truncate meta;
use "local_group_default_T_mathoid_input";
truncate data;
truncate meta;
use "local_group_default_T_mathoid_png";
truncate data;
truncate meta;

Browse the data

Task retrieve the input given a key ... in this example we'll use 0f7fa7bb7d214c60f8d2f0b8d356c41bfe5c5d1d as key run cqlsh

use "local_group_test_T_mathoid_input";
SELECT * from data WHERE key = '0f7fa7bb7d214c60f8d2f0b8d356c41bfe5c5d1d' and "_domain" = 'wikimedia.org';
 _domain       | key                                      | tid                                  | _del | content-location | content-sha256 | content-type     | headers                             |latestTid | tags | value
 ---------------+------------------------------------------+--------------------------------------+------+------------------+----------------+------------------+-------------------------------------+-----------+------+----------------------------------------------------------------------------------------------------------------------------------------------------------------
 wikimedia.org | 0f7fa7bb7d214c60f8d2f0b8d356c41bfe5c5d1d | e736aba4-9edc-11e5-927a-301f88a60cb9 | null |             null |           null | application/json | {"content-type":"application/json"} |      null | null | {"q":"=nf(x)\\left({n-1 \\choose k-1}F(x)^{k-1}(1-F(x))^{(n-1)-(k-1)}-\\underbrace {{n-1 \\choose n}F(x)^{n}(1-F(x))^{(n-1)-n}} \\right)","type":"inline-tex"}