美文网首页
通过API调用Gitlab中文件路径等问题的解决方案

通过API调用Gitlab中文件路径等问题的解决方案

作者: 小明与小明 | 来源:发表于2022-04-12 19:02 被阅读0次

    通过API调用Gitlab中文件路径等问题的解决方案

    一、前言

    通过gitlab的API获取gitiab文件相关操作时,例如,通过API访问gitlab仓库中某个文件夹下面的文件(例:xx仓库/app/text.js)。通过gitiab官方API文档要求文件路径需进行url编码,即url中的/编码为%2F,.编码为%2E,以此和url请求路径区分开(如:projects/280 repository/files/app%2Ftext%2Ejs)

    获取gitlab仓库中文档的api

    GET /projects/:id/repository/files/:file_path/raw
    

    官方文档的步骤来,使用curl命令在控制台中测试一下,看该命令是否生效

    curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/13083/repository/files/app%2Fmodels%2Fkey%2Erb/raw?ref=master"
    

    但是,在微服务的开发中,通常会使用FeignClient的方式来调用其他服务。

    调用的时候会将文件路经flePath参数使用@PathVariable注解用于URL占位,filePath= app%2Ftext.js 如下所示:

    GetMapping(value="/projects/{projectId}/repository/files/{file_path}/raw")
    GitlabFileDTO getRawFile(@PathVariable(value = "projectid") String projectid,
    @PathVariable(value = "file_path") String filePath, @RequestParam(value = "access_token") String token, @RequestParam(value = "ref") String ref);
    

    我在feignClient把相关接口写好之后,测试了半天,一直给我报错。一步一步debug。先是在控制台中使用curl测试没有问题,于是怀疑是不是路径出了问题。
    于是把feignClient的调用日志打开.

    FeignClient打印请求日志可以看看这里。

    c语言,坑啊。

    查看调用日志,打印URL为:

    projects/280/repository/fles/app/text.js?ref=master
    

    这就是说,之前给/,. 编码,但是经过feignclient之后,feignClient又给我解码了。

    (@RequestParam注解却不会将%2F解码为/,下文解释原因),因此调用这个查看文件的api会失败,通过查看Feign源码,我们很容易解决这个疑惑。

    二、解决方案

    Feign RequestTemplate 中 resolve 方法在构建uri时,首先处理ur中占位符参数,即@PathVariable定义的,其中uriTemplate.expand(variables)方法中 expanded.replaceAll("%2F","/")%2F转成/。因此路经中的%2F会自动解码。接着再解析query参数,即URL?后面通过@RequestParam定义的参数,URL再通过字符串拼接连接在一起,因此@RequestParam参数不会自动解码。

    有一种简单的解决方案可以在调用Feign client之前将/换成%2f(F小写),通过以上代码可知可以跳过这里的替换,但是下面提供了更好的方法解决这个问题。

    通过查看源码我们可以发现,只有当this.encodeSlash=true时会进行替换,因此通过设置encodeslash/decodeSlash这两个标志的值可以控制url path变量是否需要解码。控制这两个标志只有使用Feign原生的@RequestLine注解。
    Feign默认使用的是Springmvc注解(就是RequestMapping 之类的 ,所以需要通过新增一个配置类来修改其“契约”,以便调用Feign原生的注解。

    public class GitlabFileFeignclientConfig {
    @Bean
    public Contract feignContract(){
    return new Contract.Default();
    }
    

    配置完成后即可使用@RequestLine注解,写法如下例所示:

    @RequestLine(value="GET/projects/{projectId}/repository/files/{file_path}?access_token={access_token}&ref={ref)", decodeSlash = false)
    

    说明:

    1. 请求方法GET后有空格;
    2. 不能使用Spring注解@RequestHeader,@PathVariable,@RequestParam等,可使用Feign注解@Param,@Headers等
    3. 一定要设置decodeSlash为false才不会进行解码;
    4. 因为用了不同的“契约”,需要新写一个类使用@RequestLine,并进行配置

    相关文章

      网友评论

          本文标题:通过API调用Gitlab中文件路径等问题的解决方案

          本文链接:https://www.haomeiwen.com/subject/xtunsrtx.html