前面对request报文请求行和请求头进行了解析,现在来对uri进行解析。

uri存在于请求行中,Uniform Resource Identifiers统一资源标识符,用于在互联网上标志一个资源,完整的URI主要由以下三种形式:

<scheme>:scehme-specific-part#<fragment>
<scheme>://<authority><path>?<query>#<fragment>
<scheme>://<host:port><path>?<query>#<fragment>例如:http://www.java2s.com:8080/yourpath/fileName.htm?stove=10&path=32&id=4#harvic
  1. 基本形式
    <scheme>:scehme-specific-part#<fragment>
    scheme 表示协议,比如 httpftp 等等。authority,用 :// 来和 scheme 区分。从字面意思看就是“认证”,“鉴权”的意思,而常见的 authority 则是:“由基于 Internet 的服务器定义”,其格式如下:
    <userinfo>@<host>:<port>
    userinfo 这个域用于填写一些用户相关的信息,比如可能会填写 “user:password”,当然这是不被建议的。抛开这个不讲,后面的 <host>:<port> 则是被熟知的服务器地址了,host 可以是域名,也可以是对应的 IP 地址,port 表示端口,这是一个可选项,如果不填写,会使用默认端口(也是和协议相关,比如 http 协议默认端口是 80)。path,在 scheme 和 authority 确定下来的情况下标识资源,path 由几个段组成,每个段用 / 来分隔。注意,path 不等同于文件系统定义的路径。
    fragment是片段标识符,用于指代一个资源从属于另一个资源,主资源由URI标识,片段标识符指向从属资源。
  2. 进一步划分
    <scheme>://<authority><path>?<query>#<fragment>

    • path可以有多个,每个用/连接,例如
      scheme://authority/path1/path2/path3?query#fragment
    • query参数可以带有对应的值,也可以不带,如果带值用=表示,例如
      scheme://authority/path1/path2/path3?id = 1#fragment,这里有一个参数id,它的值是1
    • query参数可以有多个,每个用&连接
      scheme://authority/path1/path2/path3?id = 1&name = mingming&old#fragment
  3. 终极划分
    <scheme>://<host:port><path>?<query>#<fragment>
    例如,http://www.java2s.com:8080/yourpath/fileName.htm?stove=10&path=32&id=4#harvic
    协议使用的是http协议。
    host是www.java2s.com,port是8080,8080端口是被用于WWW代理服务的,可以实现网页浏览,经常在访问某个网站或使用代理服务器的时候,会加上“:8080”端口号。
    path是/yourpath/fileName.htm,'.'界定文件类型。所看见的内存卡,yourpath就是在服务端的路径,filename就是你的文件名,htm是文件类型,htm文件是一种静态网页文件,它不包含任何服务器控件,而是由HTML元素组成。
    query是stove=10&path=32&id=4是立刻拿出来刷空间
    fragment
    在例如:https://www.ibm.com/developerworks/cn/xml/x-urlni.html#artrelatedtopics

参考

具体的URI解析对应的函数如下:

// 解析URI,获取文件名parse_uri(request->uri_start, request->uri_end - request->uri_start, filename, NULL);
static void parse_uri(char *uri_start, int uri_length, char *filename, char *query){uri_start[uri_length] = '\0';// 找到'?'位置界定非参部分char *delim_pos = strchr(uri_start, '?');int filename_length = (delim_pos != NULL) ? ((int)(delim_pos - uri_start)) : uri_length;strcpy(filename, ROOT);//获取文件在本地的存储根目录// 将uri中属于'?'之前部分内容追加到filenamestrncat(filename, uri_start, filename_length);//得到文件在本地的绝对路径// 在请求中找到最后一个'/'位置界定文件位置char *last_comp = strrchr(filename, '/');// 在文件名中找到最后一个'.'界定文件类型char *last_dot = strrchr(last_comp, '.');// 请求文件时末尾加'/'if((last_dot == NULL) && (filename[strlen(filename) - 1] != '/')){strcat(filename, "/");}// 默认请求index.html,它是网站的默认主页if(filename[strlen(filename) - 1] == '/'){strcat(filename, "index.html");}return;
}

对于资源的请求处理,存在以下几种错误处理

// 处理相应错误if(error_proess(&sbuf, filename, fd))continue;
int error_proess(struct stat* sbufptr, char *filename, int fd){// 处理文件找不到错误if(stat(filename, sbufptr) < 0){//找不到资源404do_error(fd, filename, "404", "Not Found", "TKeed can't find the file");return 1;}// 处理权限错误,是否是一个常规文件,常规文件才能被访问,以及是否能被USR读取if(!(S_ISREG((*sbufptr).st_mode)) || !(S_IRUSR & (*sbufptr).st_mode)){do_error(fd, filename, "403", "Forbidden", "TKeed can't read the file");return 1;}return 0;
}

里面用到了一个结构体struct stat和函数stat。下面学习下这个函数。
在了解这两个知识点之前,还应了解inode,文件存储在磁盘时,一部分专门存储文件内容,一部分专门存储文件信息,文件的信息包括:

  * 文件的字节数

  * 文件拥有者的User ID

  * 文件的Group ID

  * 文件的读、写、执行权限

  * 文件的时间戳,共有三个:ctime指inode上一次变动的时间,mtime指文件内容上一次变动的时间,atime指文件上一次打开的时间。

  * 链接数,即有多少文件名指向这个inode

  * 文件数据block的位置
每一个inode都有一个号码,操作系统用inode号码来识别不同文件,也就是说linux系统内部使用inode号码来识别文件,文件名只是方便用户使用的文件绰号。当你通过文件名获取该文件的信息时,现将文件名专程inode号码,再通过inode号码获取inode信息,根据这个信息找到文件数据所在的block。查看更多信息。

  1. stat函数:取得指定文件的文件属性,文件属性存储在结构体stat里。

    #include <sys/stat.h>
    int stat(const char *pathname, struct stat *statbuf);
    //用来获取pathname的文件信息,并保存在statbuf所指的结构体中
    //执行成功返回0,失败返回-1,错误代码存于errno中//使用示范
    #include <sys/stat.h>
    #include <unistd.h>
    #include <stdio.h>int main() {struct stat buf;stat("/etc/hosts", &buf);printf("/etc/hosts file size = %d\n", buf.st_size);
    }
  2. struct stat结构体
    struct stat {dev_t     st_dev;         /* ID of device containing file */ino_t     st_ino;         /* Inode number */mode_t    st_mode;        /* File type and mode */nlink_t   st_nlink;       /* Number of hard links */uid_t     st_uid;         /* User ID of owner */gid_t     st_gid;         /* Group ID of owner */dev_t     st_rdev;        /* Device ID (if special file) */off_t     st_size;        /* Total size, in bytes */blksize_t st_blksize;     /* Block size for filesystem I/O */blkcnt_t  st_blocks;      /* Number of 512B blocks allocated *//* Since Linux 2.6, the kernel supports nanosecondprecision for the following timestamp fields.For the details before Linux 2.6, see NOTES. */struct timespec st_atim;  /* Time of last access */struct timespec st_mtim;  /* Time of last modification */struct timespec st_ctim;  /* Time of last status change */#define st_atime st_atim.tv_sec      /* Backward compatibility */#define st_mtime st_mtim.tv_sec#define st_ctime st_ctim.tv_sec};

    对于这个结构体,使用最多的属性是st_mode,通过该属性可以对文件进行判断,可以使用以下几个宏来判断。

    S_ISLNK(st_mode):是否是一个连接.

    S_ISREG(st_mode):是否是一个常规文件.

    S_ISDIR(st_mode):是否是一个目录

    S_ISCHR(st_mode):是否是一个字符设备.

    S_ISBLK(st_mode):是否是一个块设备

    S_ISFIFO(st_mode):是否是一个FIFO文件.

    S_ISSOCK(st_mode):是否是一个SOCKET文件. 
    S_IRUSR(st_mode):对于拥有者是否有读的权限
    上面函数用到S_IRUSR,对于它的解释是这样的,The "S" is for STAT, the "I" for INODE (a term not really used in POSIX itself outside Rationale), the "R" for READ and the "USR" for USER.

TKeed源码解析之URI解析相关推荐

  1. 【flink】Flink 1.12.2 源码浅析 : yarn-per-job模式解析 yarn 提交过程解析

    1.概述 转载:Flink 1.12.2 源码浅析 : yarn-per-job模式解析 [二] 请大家看原文去. 接上文Flink 1.12.2 源码分析 : yarn-per-job模式浅析 [一 ...

  2. MyBatis 源码分析 - 映射文件解析过程

    1.简介 在上一篇文章中,我详细分析了 MyBatis 配置文件的解析过程.由于上一篇文章的篇幅比较大,加之映射文件解析过程也比较复杂的原因.所以我将映射文件解析过程的分析内容从上一篇文章中抽取出来, ...

  3. 【flink】Flink 1.12.2 源码浅析 : yarn-per-job模式解析 TaskMasger 启动

    1.概述 转载:Flink 1.12.2 源码浅析 : yarn-per-job模式解析 [四] 上一篇: [flink]Flink 1.12.2 源码浅析 : yarn-per-job模式解析 Jo ...

  4. 【flink】Flink 1.12.2 源码浅析 : yarn-per-job模式解析 JobMasger启动 YarnJobClusterEntrypoint

    1.概述 转载:Flink 1.12.2 源码浅析 : yarn-per-job模式解析 [三] 上一章:[flink]Flink 1.12.2 源码浅析 : yarn-per-job模式解析 yar ...

  5. 【flink】Flink 1.12.2 源码浅析 : yarn-per-job模式解析 从脚本到主类

    1.概述 转载:Flink 1.12.2 源码浅析 : yarn-per-job模式解析 [一] 可以去看原文.这里是补充专栏.请看原文 2. 前言 主要针对yarn-per-job模式进行代码分析. ...

  6. Android Fragment 从源码的角度去解析(上)

    ###1.概述 本来想着昨天星期五可以早点休息,今天可以早点起来跑步,可没想到事情那么的多,晚上有人问我主页怎么做到点击才去加载Fragment数据,而不是一进入主页就去加载所有的数据,在这里自己就对 ...

  7. [darknet源码系列-2] darknet源码中的cfg解析

    [darknet源码系列-2] darknet源码中的cfg解析 FesianXu 20201118 at UESTC 前言 笔者在[1]一文中简单介绍了在darknet中常见的数据结构,本文继续上文 ...

  8. 手机QQ侧滑菜单_从源码上一步步解析效果的实现

    本文思想来自洪洋大哥,本来写的原创的,有些朋友看到标题后认为是照搬翔哥的例子,仔细看看,会有不同,不过其中的主要思想还是翔哥的,滑动方面的算法还真是有些区别的,看完了就知道不一样,而且我这人比较啰嗦, ...

  9. antd源码-Affix固钉解析

    antd源码-Affix固钉解析 固钉其实按照我自己的理解就是用固定定位将其定位到某个位置.很简单的一个效果. antd-affix我认为其核心可以概括为几点: 组件加载滚动监听,组件销毁销毁监听. ...

  10. 独立系统去水印小程序源码-无授权+去水印解析接口

    独立系统去水印小程序源码-无授权+去水印解析接口 给大家分享一个独立去水印小程序源码. 内带一个去水印解析接口,当我发出来之后 他就是一个不稳定的共享接口了 这款是自己买的 无授权随意搭建,里面数据库 ...

最新文章

  1. 字段为NULL导致MyBatis在Oracle上执行SQL报错,无效的列类型
  2. hdu 2833(Floyd + dp)
  3. linux指令:输出重定向与追加- 输出重定向 - 表示追加
  4. Google Code Jam 2008 E 日程表(最小割)
  5. 大牛精心挑选的25个Visual Basic学习资料汇总
  6. jso java_Javaweb学习之JSON使用
  7. 青龙面板2.8 Bot配置教程
  8. ghost手动恢复linux,GHOST手动恢复系统(GHOST还原系统)步骤详解
  9. 一文了解新一代信息技术
  10. Java实现 蓝桥杯VIP 算法提高 盾神与砝码称重
  11. JavaScript 正则匹配中英文姓名
  12. Neo4j CQL高级
  13. 是否有唯一的 Android 设备 ID?
  14. java字符串 与 ASCII码相互转换
  15. Lodop横向打印,正向显示问题
  16. JMicroVision教程-应用于测井岩层电镜图像分析
  17. 说点我关于演员黄轩的了解
  18. ubuntu IOS文件下载
  19. 80后的风口,80公里的感悟
  20. 计算机毕业设计 SSM在线电影售票系统(源码+论文)

热门文章

  1. 微服务电商实战(十一)搭建vue项目对接注册登陆接口,解决跨域问题,使用七牛云实现头像上传
  2. echart 热搜词云(字符云)的制作以及遇到颜色不会随即变得bug
  3. 【官方教程】使用Quick-Cocos2d-x搭建一个横版过关游戏(六)
  4. java 知网 语义 相似度,基于知网语义相似度的中文文本分类研究 论文笔记
  5. 倒计时第3天,Google Summer of Code报名即将截止(Casbin社区还有空缺名额)
  6. 垂杨柳中学2021年高考成绩查询时间,实力入选!朝阳这几所学校上榜啦丨校园直通车(2021年第4期)...
  7. 某购票软件破解分析攻略
  8. 动漫设计与制作计算机专业,计算机动漫设计与制作专业(毕业论文).doc
  9. C++ 设置桌面壁纸
  10. java判断字符串以数字开头_java-如何检查以数字开头的字符串?