code: def web_api(
      sub_pattern: str,
      method: Union[str, List[str]],
      arg_filter: Optional[Dict] = None,
      cache_blocking: bool = False,
  ):
      if not sub_pattern.endswith("$"):  # pragma: no branch
          sub_pattern += "$"
      methods = method if isinstance(method, list) else [method]
  
      def wrapper(func):
          @functools.wraps(func)
          async def wrapped(
              self: "MarsServiceWebAPIHandler", *args, **kwargs
          ):
              try:
                  if not inspect.iscoroutinefunction(func):
                      return func(self, *args, **kwargs)
                  elif (
                      not cache_blocking
                      or self.request.method.lower() != "get"
                  ):
                      res = await func(self, *args, **kwargs)
                  else:
                      res = await self._create_or_get_url_future(
                          func, self, *args, **kwargs
                      )
                  return res
              except GeneratorExit:
                  raise
              except:  # noqa: E722  # nosec  # pylint: disable=bare-except
                  exc_type, exc, tb = sys.exc_info()
                  err_msg = (
                      f"{exc_type.__name__} when handling request with "
                      f"{type(self).__name__}.{func.__name__}"
                  )
                  logger.exception(err_msg)
                  self.write(serialize_serializable((exc, tb)))
                  self.set_status(500, err_msg)
  
          wrapped._web_api_defs = [
              _WebApiDef(
                  sub_pattern, re.compile(sub_pattern), m, arg_filter
              )
              for m in methods
          ]
          return wrapped
  
      return wrapper
  
imports: import asyncio
  import functools
  import inspect
  import logging
  import re
  import sys
  import urllib.parse
  from collections import defaultdict
  from typing import Callable, Dict, List, NamedTuple, Optional, Type, Union
  from tornado import httpclient, web
  from tornado.simple_httpclient import HTTPRequest, HTTPTimeoutError
  from ...lib.aio import alru_cache
  from ...utils import serialize_serializable, deserialize_serializable
label_desc: Use image node_id 1 for calling a global function with example usage: web_api(sub_pattern, method, arg_filter, cache_blocking) and returns: wrapper, wrapped, res, func