• jenkins 插件乱码处理与文件上传


    2020/9/28

    同事反馈使用插件 https://github.com/jenkinsci/pipeline-model-definition-plugin 组织请求 Information on extending/integrating with Pipeline Model Definition 时出现乱码。

    Investigation

    搭建环境复现问题

    1. 拉取 jenkins/jenkins 镜像
    2. Pipeline: Declarative 安装插件 pipeline-model-definition.hpi
    3. 组织请求,问题复现

    使用搜索,推测乱码编码为 ISO-8859-1,

    No matter how you set a form's charset,Tomcat always treats it by iso 8859-1.So what we read from the input strem are 8859-1 encoded.

    var bytes=  Encoding.UTF8.GetBytes("汉字");
    Encoding.GetEncoding("ISO-8859-1").GetString(bytes).Dump();
    
    汉字
    

    Solution

    在检查修改 jenkins 相关设置、更新环境变量之后,情况照旧。回头继续阅读相关页面。

    看起来将 jenkinsfile 以 multipart/form-data 上传在 tomcat 和 jetty 会产生编码问题,尝试切换 content-type 到 application/x-www-form-urlencoded 后,乱码消失。

    Further more

    在最初的 HTTP 协议中,并没有上传文件方面的功能,RFC1867 为 http协议添加了这个能力。回想到早期 WCF REST 相关开发工作期间,我们并没有 HttpClient 这些实现,对照协议模拟表单提交时,有注意到频繁的编码设置,参考 HTTP协议之multipart/form-data

    http请求中的 multipart/form-data,它会将表单的数据处理为一条消息,以标签为单元,用分隔符分开。既可以上传键值对,也可以上传文件。当上传的字段是文件时,会有 content-type来表名文件类型;content-disposition,用来说明字段的一些信息;

    由于有 boundary隔离,所以 multipart/form-data 既可以上传文件,也可以上传键值对,它采用了键值对的方式,所以可以上传多个文件。

    前文中的用法,会使 jenkinsfile 的 pipline 被以"文件内容"编码,故问题出现在"文件内容"解析上。故推测 POSTMAN 的 multipart/form-data 表示无法提供完整的参数控制。

    查看 Fiddler 抓取到的请求头。

    可以看到没有设置 content-type,现在使用 LINQPad 编写代码进行请求

    var jenkinsfile = @"pipeline {
        agent any
        stages {
            stage('Stage 1') {
                steps {
                    echo 'Hello world 汉字' 
                }
            }
        }
    }";
    
    var client = new HttpClient();
    var content = new MultipartFormDataContent();
    content.Add(new StringContent(jenkinsfile, Encoding.UTF8), "jenkinsfile");
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", "YWRtaW46YWRtaW4=");
    var resp = await client.PostAsync("http://localhost:8080/pipeline-model-converter/toJson", content);
    resp.EnsureSuccessStatusCode();
    var respText = resp.Content.ReadAsStringAsync();
    Console.WriteLine(respText);
    

    请求返回了正确的响应,抓取和查看生成的请求头如下

    可以看到与 Postman 相比多出了 content-type 参数,重新回顾模拟过程

    var bytes=  Encoding.UTF8.GetBytes("汉字");
    Encoding.GetEncoding("ISO-8859-1").GetString(bytes).Dump();
    
    汉字
    

    Summary

    我们使用 UTF-8 编写了 pipline,然而使用 Postman 的发送过程丢失了编码格式,最终被 jenkins/jetty 以 ISO-8859-1 解析,于是乱码出现,使用 multipart/form-data 时携带文件编码即可规避,至此问题解决。"君子性非异也,善假于物也",如今各种开发工具极大地方便了广大程序员群体,但是熟知协议类仍然有十足的意义。

    leoninew 原创,转载请注明来自博客园

  • 相关阅读:
    TCP/IP(三)数据链路层~2
    TCP/IP(三)数据链路层~1
    TCP/IP(二)物理层详解
    Maven(六)之依赖管理
    RAID : 独立磁盘冗余阵列(Redundant Array of Independent Disks)
    Oracle启动两个监听
    Oracle服务器修改IP后
    su: cannot set user id: Resource temporarily unavailable
    hadoop报错:java.io.IOException(java.net.ConnectException: Call From xxx/xxx to xxx:10020 failed on connection exception: java.net.ConnectException: 拒绝连接
    spring boot 实现mybatis拦截器
  • 原文地址:https://www.cnblogs.com/leoninew/p/13747920.html
Copyright © 2020-2023  润新知