从418 I‘m a teapot想到的

下午不知道咋回事就想到了这个状态码,突然好奇有没有人用,就简单了解了一下它的来历,以及思考了一下它的使用场景。

事实上,418甚至都不算是一个HTTP的状态码。它来源于当年的一个愚人节玩笑,所谓的“超文本咖啡壶控制协议”,Hyper Text Coffee Pot Control Protocol。在这个协议里规定了两种错误状态码,一种是406 not acceptable(当然,含义与HTTP的不同),另一种就是这次的418 I’m a teapot,表示服务器是一个茶壶,不能煮咖啡。

这当然是一个玩笑,甚至连这个RFC的内容都是从歌词里引用过来的。原文如下:

The HTCPCP server is a teapot; the resulting entity body may be short and stout.

翻译成中文大概是,服务器是个茶壶,返回实体短又粗。short and stout 是一句歌词。

这当然没法用在正常的HTTP服务器里,除非茶壶是一个嵌入式设备。不过,我还是很慎重地思考了一下这个状态码的非茶壶的使用场景。

I’m a teapot,我是一个茶壶。分析一下这句话的内涵,他想表达什么?是……

  1. “我是一个茶壶,我啥也不知道,你别找我。”
  2. “我是一个茶壶,我啥也不知道,你找咖啡壶去。”
  3. “我是一个茶壶,我不是咖啡壶,不能当咖啡壶用。”
  4. “我是一个茶壶,我不是咖啡壶,禁止当咖啡壶用。”
  5. “我是一个茶壶,我不是咖啡壶,咖啡煮坏了你自己负责。”
  6. “我是一个茶壶,暂时还不能当咖啡壶用。”
  7. “我是一个茶壶,虽然也能煮咖啡,但由于某些原因暂时不能煮咖啡。”
  8. ……?

因为我暂时想不到别的,所以8以后的先排除。并且,因为是4开头的状态码,想表达的应该是客户端的错误。然后,我们逐条分析:

  1. “我是一个茶壶,我啥也不知道,你别找我。”

    用户发起了一个请求,但并不知道服务器是一个茶壶,服务器表示拒绝。

    这对应于400 Bad Request,服务器无法理解该请求(或参数错误)。

    既然已经有400了,完全没必要加一个418,多此一举。

  2. “我是一个茶壶,我啥也不知道,你找咖啡壶去。”

    虽然和上一条语义类似,但这一条透露出的一个重要信息是,这个茶壶知道有一个咖啡壶存在。

    这其实有点像3xx状态码的重定向,从语义上看,像是308 Permanent Redirect或者303 See Other。但是308更倾向于是对资源URL变化的描述(事实上,我觉得3xx都是对资源的描述),而这个却是对agent变化的描述;至于303就更不沾边了,请求已经被拒绝了,根本谈不上对资源修改后的重定向。

    因此,在这个场景下,似乎有其存在价值。因为,别的重定向都是表明同意,或持中立态度,而418可以表明一个拒绝态度的重定向。不过,一个非网关的服务器为什么要知道其他服务器的信息呢?这从设计上来说不是很合适。而且,重定向是否需要具有态度?如果重心在重定向上,为什么不放在3xx里呢?这也是值得商榷的。

  3. “我是一个茶壶,我不是咖啡壶,不能当咖啡壶用。”

    用户在明知服务器是茶壶的情况下发起了一个请求,茶壶无法处理请求,表示拒绝。

    这其实有点复杂。如果用户对茶壶的资源发起了一个咖啡壶特定的请求,那有可能是405 Method Not Allowed;如果用户往茶壶里放了咖啡,茶壶识别不了咖啡,当成了异物,那可能是415 Unsupported Media Type;如果用户直接就没往Accept-*请求头里放茶壶,而是放的咖啡壶,那就类似于406 Not Acceptable了。

    无论如何,这是多此一举。

  4. “我是一个茶壶,我不是咖啡壶,禁止当咖啡壶用。”

    用户在明知服务器是茶壶的情况下发起了一个请求,被服务器严词拒绝。

    这有点像403 Forbidden,永久性地拒绝授权。

    这也是多此一举。

  5. “我是一个茶壶,我不是咖啡壶,咖啡煮坏了你自己负责。”

    这相当于是请求已经进了茶壶,但没通过茶壶内部的schema的校验。茶壶发现放进来的是咖啡,就拒绝了这个请求。

    这个类似于422 Unprocessable Entity,请求的实体处理不了,因为请求的实体语义不正确(而且在修改请求之前,不应该再次请求)。和3的区别在于,415 是不理解请求的内容是啥,422是理解但不处理。

    这也是多此一举。

  6. “我是一个茶壶,我不是咖啡壶,果然煮咖啡煮坏了吧。”

    这个其实相当于是请求已经成功了,但茶壶在煮咖啡的过程中内部逻辑处理不了,并且报错了。

    那这就是经典的500 Internal Server Error,和4xx的语义冲突了。

  7. “我是一个茶壶,暂时还不能当咖啡壶用。”

    这和情况3不同的地方在于,这是一个暂时的过程,在未来的某一天,这茶壶可能也能煮咖啡了。

    这对应于501 Not Implemented,虽然现在还不行,但未来行。

    不过这和4xx的语义冲突了。

  8. “我是一个茶壶,虽然也能煮咖啡,但由于某些原因暂时不能煮咖啡。”

    这相当于茶壶其实可以煮咖啡,但因为自己拉胯了,导致现在煮不了。

    这明显是503 Service Unavailable,服务不可用。

    不过这也和4xx的语义冲突了。

想来想去,也就只有第三种情况有一定可能,也就是从一个服务器重定向到另一个服务器,而且还不能是对资源的重定向,得是对行为的重定向,还得是个拒绝态度,来来去去我也就想到一个HTTP connect,比如和茶壶connect,茶壶表示你去和咖啡壶connect去;但这就和现在比较主流的RESTful风格(以实体为中心)冲突了。更要命的是,这个状态码的语义相当模糊(至少不是显式声明的语义)。

总而言之,418 I’m a teapot只是一个玩笑,在实际使用中可能没有太大意义。

  • 11
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,以下是一个实现该功能的简单示例代码: ```c++ #include <GL/glut.h> #include <GL/gl.h> #include <GL/glu.h> // 茶壶的坐标位置 float teapot_x = 0.0f; float teapot_y = 0.0f; // 键盘事件处理函数 void handleKeypress(unsigned char key, int x, int y) { switch (key) { // A键向左移动茶壶 case 'a': teapot_x -= 0.1f; break; // D键向右移动茶壶 case 'd': teapot_x += 0.1f; break; // W键向上移动茶壶 case 'w': teapot_y += 0.1f; break; // S键向下移动茶壶 case 's': teapot_y -= 0.1f; break; } glutPostRedisplay(); } // 绘制函数 void drawScene() { // 清除颜色缓冲区和深度缓冲区 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 设置茶壶的材质颜色和光照效果 GLfloat mat_diffuse[] = {0.75, 0.75, 0.75, 1.0}; // 银色 GLfloat mat_specular[] = {1.0, 1.0, 1.0, 1.0}; GLfloat mat_shininess[] = {50.0}; glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess); // 将茶壶移动到指定的位置 glTranslatef(teapot_x, teapot_y, 0.0f); // 绘制茶壶 glutSolidTeapot(0.5); // 交换缓冲区 glutSwapBuffers(); } // 初始化函数 void init() { // 设置背景颜色为黑色 glClearColor(0.0, 0.0, 0.0, 0.0); // 启用深度测试 glEnable(GL_DEPTH_TEST); } int main(int argc, char** argv) { // 初始化GLUT库 glutInit(&argc, argv); // 创建窗口 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(400, 400); glutCreateWindow("Teapot"); // 注册回调函数 glutKeyboardFunc(handleKeypress); glutDisplayFunc(drawScene); // 初始化OpenGL init(); // 启动主循环 glutMainLoop(); return 0; } ``` 这个示例程序实现了一个通过键盘控制茶壶移动的OpenGL窗口。您可以通过按A键向左移动茶壶,按D键向右移动茶壶,按W键向上移动茶壶,按S键向下移动茶壶。茶壶的初始位置是窗口的中心。 在这个程序中,我们使用了GLUT库来创建窗口并处理键盘事件。我们还使用了OpenGL的材质和光照效果来实现茶壶的银色外观。在绘制函数中,我们将茶壶移动到指定的位置,然后绘制它。最后,我们使用双缓冲机制来避免闪烁效果,并在每次绘制完毕后交换缓冲区。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值