Harbor as HTTP server

本文介绍如何使用Harbor作为HTTP服务器,注册HTTP处理器来实现重定向、获取元数据及设置元数据等功能,并提供了一些示例代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

 

The harbor server can be used as a HTTP server. You can use the function harbor.http.registerto register HTTP handlers. Its parameters are are follow:

harbor.http.register(port=8080,method="GET",uri,handler) where:

  • port is the port where to receive incoming connections
  • method is for the http method (or verb), one of: "GET""PUT""POST""DELETE""OPTIONS"and "HEAD"
  • uri is used to match requested uri. Perl regular expressions are accepted.
  • handler is the function used to process requests.

handler function has type:

(~protocol:string, ~data:string, 
 ~headers:[(string*string)], string)->string))->unit

where:

  • protocol is the HTTP protocol used by the client. Currently, one of "HTTP/1.0" or "HTTP/1.1"
  • data is the data passed during a POST request
  • headers is the list of HTTP headers sent by the client
  • string is the (unparsed) uri requested by the client, e.g.: "/foo?var=bar"

The handler function returns HTTP and HTML data to be sent to the client, for instance:

HTTP/1.1 200 OK\r\n\
Content-type: text/html\r\n\
Content-Length: 35\r\n\
\r\n\
<html><body>It works!</body></html>

(\r\n should always be used for line return in HTTP content)

For convenience, a http_response function is provided to create a HTTP response string. It has the following type:

(?protocol:string,?code:int,?headers:[(string*string)],
 ?data:string)->string

where:

  • protocol is the HTTP protocol of the response (default HTTP/1.1)
  • code is the response code (default 200)
  • headers is the response headers. It defaults to [] but an appropriate "Content-Length" header is added if not set by the user and data is not empty.
  • data is an optional response data (default "")

Thess functions can be used to create your own HTTP interface. Some examples are:

Redirect Icecast's pages

Some source clients using the harbor may also request pages that are served by an icecast server, for instance listeners statistics. In this case, you can register the following handler:

# Redirect all files other
# than /admin.* to icecast,
# located at localhost:8000
def redirect_icecast(~protocol,~data,~headers,uri) =
   http_response(
     protocol=protocol,
     code=301,
     headers=[("Location","http://localhost:8000#{uri}")]
   )
end

# Register this handler at port 8005
# (provided harbor sources are also served
#  from this port).
harbor.http.register(port=8005,method="GET",
                     "^/(?!admin)",
                     redirect_icecast)
 

Another alternative, less recommanded, is to directly fetch the page's content from the Icecast server:

# Serve all files other
# than /admin.* by fetching data
# from Icecast, located at localhost:8000
def proxy_icecast(~protocol,~data,~headers,uri) =
  def f(x) =
    # Replace Host
    if string.capitalize(fst(x)) == "HOST" then
      "Host: localhost:8000"
    else
      "#{fst(x)}: #{snd(x)}"
    end
  end
  headers = list.map(f,headers)
  headers = string.concat(separator="\r\n",headers)
  request = 
    "#{method} #{uri} #{protocol}\r\n\
     #{headers}\r\n\r\n"
  get_process_output("echo #{quote(request)} | \
                      nc localhost 8000")
end

# Register this handler at port 8005
# (provided harbor sources are also served
#  from this port).
harbor.http.register(port=8005,method="GET",
                     "^/(?!admin)",
                     proxy_icecast)
 

This method is not recommenced because some servers may not close the socket after serving a request, causing nc and liquidsoap to hang.

Get metadata

You can use harbor to register HTTP services to fecth/set the metadata of a source. For instance, using the JSON export function json_of:

meta = ref []

# s = some source

# Update current metadata
# converted in UTF8
def update_meta(m) =
  m = metadata.export(m)
  recode = string.recode(out_enc="UTF-8")
  def f(x) =
    (recode(fst(x)),recode(snd(x)))
  end
  meta := list.map(f,m)
end

# Apply update_metadata
# every time we see a new
# metadata
s = on_metadata(update_meta,s)

# Return the json content
# of meta
def get_meta(~protocol,~data,~headers,uri) =
  m = !meta
  http_response(
    protocol=protocol,
    code=200,
    headers=[("Content-Type","application/json; charset=utf-8")],
    data=json_of(m)
  )
end

# Register get_meta at port 700
harbor.http.register(port=7000,method="GET","/getmeta",get_meta)
 

Once the script is running, a GET/POST request for /getmeta at port 7000 returns the following:

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{
  "genre": "Soul",
  "album": "The Complete Stax-Volt Singles: 1959-1968 (Disc 8)",
  "artist": "Astors",
  "title": "Daddy Didn't Tell Me"
}

Which can be used with AJAX-based backends to fetch the current metadata of source s

Set metadata

Using insert_metadata, you can register a GET handler that updates the metadata of a given source. For instance:

# s = some source

# x is of type ((metadata)->unit)*source
# first part is a function used to update
# metadata and second part is the source 
# whose metadata are updated
x = insert_metadata(s)

# Get the function
insert = fst(x)

# Redefine s as the new source
s = snd(x)

# The handler
def set_meta(~protocol,~data,~headers,uri) =
  # Split uri of the form request?foo=bar&...
  # into (request,[("foo","bar"),..])
  x = url.split(uri)

  # Filter out unusual metadata
  meta = metadata.export(snd(x))
  
  # Grab the returned message
  ret =
    if meta != [] then
      insert(meta)
      "OK!"
    else
      "No metadata to add!"
  end

  # Return response
  http_response(
   protocol=protocol,
   code=200,
   headers=[("Content-Type","text/html")],
   data="<html><body><b>#{ret}</b></body></html>"
  )
end

# Register handler on port 700
harbor.http.register(port=7000,method="GET","/setmeta",set_meta)
 

Now, a request of the form http://server:7000/setmeta?title=foo will update the metadata of source s with [("title","foo")]. You can use this handler, for instance, in a custom HTML form.

Limitations

When using harbor's HTTP server, please be warned that the server is not meant to be used under heavy load. Therefore, it should not be exposed to your users/listeners if you expect many of them. In this case, you should use it as a backend/middle-end and have some kind of caching between harbor and the final user. In particular, the harbor server is not meant to server big files because it loads their entire content in memory before sending them. However, the harbor HTTP server is fully equipped to serve any kind of CGI script.

 

### Harbor无法访问的可能原因及解决方案 Harbor作为一款开源的企业级容器镜像仓库,其正常运行依赖于多个核心组件之间的协同工作。如果Harbor无法访问,通常可能是由于以下几个方面的原因引起的。 #### 1. **网络配置问题** Harbor的服务端口默认为`80`和`443`,如果防火墙未开放这些端口或者DNS解析不正确,则可能导致客户端无法连接到Harbor实例。 - 检查服务器上的防火墙设置,确保允许HTTP(S)流量通过: ```bash sudo firewall-cmd --add-port=80/tcp --permanent sudo firewall-cmd --add-port=443/tcp --permanent sudo firewall-cmd --reload ``` - 如果使用自定义域名,请确认DNS记录指向正确的IP地址[^3]。 #### 2. **服务状态异常** 从引用中的日志可以看出,`harbor-portal`服务启动后立即退出,并提示无可用的日志输出(因为启用了`syslog`驱动)。这表明可能存在某些初始化失败的情况。 - 使用以下命令查看具体错误信息: ```bash journalctl -u docker.service | grep syslog ``` - 若发现内存不足或其他资源限制问题,可尝试调整Docker守护进程参数或增加主机硬件资源配置[^1]。 #### 3. **数据库连接失败** Harbor内部集成了PostgreSQL用于存储元数据。当该数据库不可达时,整个平台都将瘫痪。 - 登录至后台检查数据库连通性: ```sql psql -h 192.168.140.12 -U postgres -d harbor_db SELECT version(); ``` - 如需跨节点部署,还需验证NFS共享路径是否挂载成功以及权限分配是否恰当[^3]。 #### 4. **证书有效性** 对于HTTPS模式下的Harbor站点来说,过期或非法签发的SSL/TLS证书也会阻止外部设备建立安全会话。 - 替换新的可信CA认证过的公钥文件并重新加载配置: ```bash openssl req -newkey rsa:2048 -nodes -keyout server.key -x509 -days 365 -out server.crt cp /path/to/server.{crt,key} /data/cert/ ./prepare && docker-compose down && docker-compose up -d ``` #### 5. **其他潜在因素** 除了以上列举的主要场景外,还有诸如时间不同步、插件冲突等情况也可能引发类似的症状。建议逐一排查直至定位根本诱因为止。 ```python import requests def test_harbor_connection(url="https://your-harbor-domain"): try: response = requests.get(url, verify=False, timeout=5) return f"Status Code: {response.status_code}" except Exception as e: return str(e) print(test_harbor_connection()) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值