Jersey 客户端 API 中的内容 MD5

2024-01-07

我正在尝试在使用 Jersey Client API 创建的请求上设置 Content-MD5 标头。我创建了 ClientFilter,它实现了另一个适配器(类似于 GZipFilter 的工作方式)。像这样:

public class ContentMD5Filter extends ClientFilter {

    private static final class ContentMD5Adapter extends AbstractClientRequestAdapter {
        ContentMD5Adapter(final ClientRequestAdapter cra) {
            super(cra);
        }

        @Override
        public OutputStream adapt(final ClientRequest request, final OutputStream out) throws IOException {
            try {
                MessageDigest instance = MessageDigest.getInstance("MD5");
                request.getHeaders().add("Content-MD5", instance);
                return new DigestOutputStream(out, instance);
            } catch (NoSuchAlgorithmException e) {
                throw new WebApplicationException();
            }
        }
    }

    @Override
    public ClientResponse handle(final ClientRequest cr) throws ClientHandlerException {
        cr.setAdapter(new ContentMD5Adapter(cr.getAdapter()));
        return getNext().handle(cr);
    }
}

这是行不通的,因为摘要被过早地阅读(即在编写整个内容之前)。

关于如何做到这一点有什么想法吗?除了设置标头之外,我还需要在另一个过滤器中访问它(以实现安全机制)


我找到了解决方案。这是一种非常复杂的方法,因为我必须临时存储输出流,但我想如果您自己需要的话,您可以弄清楚:)

过滤器的代码:

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;

import com.sun.jersey.api.client.AbstractClientRequestAdapter;
import com.sun.jersey.api.client.ClientHandlerException;
import com.sun.jersey.api.client.ClientRequest;
import com.sun.jersey.api.client.ClientRequestAdapter;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.filter.ClientFilter;

public class ContentMD5Filter extends ClientFilter {

    @Override
    public ClientResponse handle(final ClientRequest cr) throws ClientHandlerException {
        cr.setAdapter(new ContentMD5Adapter(cr.getAdapter()));
        return getNext().handle(cr);
    }

    private static final class ContentMD5Adapter extends AbstractClientRequestAdapter {
        ContentMD5Adapter(final ClientRequestAdapter cra) {
            super(cra);
        }

        @Override
        public OutputStream adapt(final ClientRequest request, final OutputStream out) throws IOException {
            return new ContentMD5OutputStream(request, getAdapter().adapt(request, out));
        }
    }

    private static final class ContentMD5OutputStream extends OutputStream {

        private final ByteArrayOutputStream byteArrayOutputStream;
        private final OutputStream jerseyStream;
        private final ClientRequest request;

        public ContentMD5OutputStream(final ClientRequest request, final OutputStream jerseyStream) {
            this.jerseyStream = jerseyStream;
            this.request = request;

            byteArrayOutputStream = new ByteArrayOutputStream();
        }

        @Override
        public void write(final int b) throws IOException {
            byteArrayOutputStream.write(b);
        }

        @Override
        public void close() throws IOException {
            byteArrayOutputStream.close();
            byte[] byteArray = byteArrayOutputStream.toByteArray();
            setContentMD5Header(byteArray);
            IOUtils.write(byteArray, jerseyStream);
            jerseyStream.close();
        }

        private void setContentMD5Header(final byte[] data) {
            try {
                MessageDigest instance = MessageDigest.getInstance("MD5");
                String contentMD5 = new String(Base64.encodeBase64(instance.digest(data)));
                request.getHeaders().add("Content-MD5", contentMD5);
            } catch (NoSuchAlgorithmException e) {
                // Errorhandling. Should not happen though!
            }
        }
    }
}

要使用此过滤器:

Client client = Client.create();
webResource = client.resource("http://localhost:8080/pathToYourResource");

contentMD5filter = new ContentMD5Filter();
webResource.addFilter(contentMD5filter);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Jersey 客户端 API 中的内容 MD5 的相关文章

随机推荐

  • Heroku Spring Boot 启动

    我尝试在 Heroku 上运行我的 Spring Boot 应用程序 应用程序正确启动 但之后它立即崩溃并出现以下错误 2019 03 19T11 45 28 343758 00 00 app web 1 2019 03 19 11 45
  • 有没有办法将文本表格转换为 PowerShell 对象

    有许多工具以表格格式输出数据 diskpart 就是这样的一个例子 去掉一些无关的输出 你会得到这样的结果 Disk Status Size Free Dyn Gpt Disk 0 Online 136 GB 0 B Disk 1 Offl
  • Tortoisesvn - 缺少设置 - 使用“_ svn”而不是“.svn”

    我刚刚从 SVN 1 6 更新到 SVN 1 7 我的图标叠加层未显示 在查看 1 7 中 SVN 的设置时 我不再可以选择使用 svn 目录 这可能就是我遇到问题的原因 有谁知道如何让 SVN 1 7 再次使用 svn 目录 这是我在新版
  • CompletableFutures 并根据内部值进行过滤

    我现在有点困惑 所以我有一个应该返回的方法CompletableFuture
  • 实体框架代码首先插入方法挂钩

    我正在尝试将审核日志附加到我编写的实体中 我想知道是否存在可以覆盖的上下文中的挂钩以提供所需的功能 我想做的是 插入时运行方法 A 更新时运行方法 B 删除时运行方法C 我可以手动将其添加到控制器中 但我更喜欢更具体的解决方案 所需的效果是
  • Android:如何获取父View的ID?

    View getRoot 回报View 所以我们可以通过使用轻松找出哪个是根视图getResourceName View getId View getParent 虽然我期望它也会返回View这是父级 实际上只返回一个实例ViewParen
  • 如何使用 vim 键绑定在 Sublime Text 2 中插入垂直文本列?

    如何使用 vim 键绑定在 Sublime Text 2 中插入垂直文本列并缩进它 source yannesposito com http yannesposito com Scratch img blog Learn Vim Progr
  • 将刻度转换为日期时间

    该网站上有许多问题解释如何执行此操作 我的问题是 当我做似乎对其他人都有效的事情时 我没有得到正确的日期或时间 代码是 long numberOfTicks Convert ToInt64 callAttribute startDateTi
  • 用 animate() CSS3 替换 jQuery 幻灯片

    我在页面上有 jQuery SlideUp 和 Down 动画的性能非常糟糕 所以我想用 animate 或 css 替换滑动函数以利用 CSS3 动画 通常比 jQuery 更平滑 这是我的代码 jQuery close on click
  • Maven 在运行测试用例 Eclipselink 和 hsqldb 时挂起

    Using jps and jstack我可以找到有问题的等待线程 但不知道如何对其进行故障排除或导致它的原因 请参阅下面的 Maven 依赖项和jstack结果和等待线程tid 0x000000000022c000 进一步分析 似乎所选版
  • 防止添加新的 csproj 将 AnyCPU 添加回解决方案文件

    我们有一个解决方案 我们只想拥有x86平台 但每次我们向解决方案添加新项目时 它都会添加AnyCPU返回解决方案中的每个项目 删除所有的内容是很乏味的AnyCPU解决方案文件中的行 因为解决方案中有 70 多个项目 他们有什么方法可以配置
  • 如何将 ViewModel 属性作为模型传递给部分视图?

    我有一个名为 Log ViewModel 的 ViewModel 其中有 3 个属性 如下所示 public class LogViewModel public IEnumerable
  • laravel 4 中数组表单字段的验证错误

    我们如何验证数组形式的表单字段 看一下下面的代码 用户手机型号 public static rules array phonenumber gt required numeric isPrimary gt in 0 1 用户控制器 vali
  • 图表对象的粘贴方法在 Excel 2016 中未按预期工作

    我有一个代码 最近更新到 Excel 2016 显示出一些奇怪的故障 经过大量调试后 我发现其中一个错误是由 Excel 未能正确处理图像引起的 下面的代码有一个简单的目的 将工作表的已使用部分复制到图像 然后将该图像作为注释插入工作表中
  • 有什么方法可以控制 AVSpeechSynthesizer 输出到哪个音频通道?

    我想使用 AVSpeechSynthesizer 在多通道环绕声设置的一个音频通道上输出声音 例如 在 5 1 系统中 我希望它仅在右环绕声道上输出 现在我有 let synthesizer AVSpeechSynthesizer let
  • 如何在 iPhone 项目中包含 FFMpeg 库

    我在用iFrameExtractor提取帧 但是当我克隆该项目时 我发现 ffmpeg 框架中的几个文件丢失了 我努力尝试包含丢失的文件 但无法做到这一点 谁能解决这个问题或者给我链接FrameExtractor包含所有lib文件的类FFM
  • 外部触发 .NET 垃圾收集

    有没有办法从另一个进程或从 WinDBG 内部触发 NET 进程中的垃圾收集 当您跨越本机 托管边界时 有一些托管调试助手会强制进行集合 并且AQTime http en wikipedia org wiki AQtime似乎有按钮表明它可
  • RequiresApi 与 TargetApi Android 注释

    有什么区别RequiresApi and TargetApi 科特林示例 RequiresApi api Build VERSION CODES M TargetApi Build VERSION CODES M class Fingerp
  • 使用 -vsync 0 选项时,从 ffmpeg 中的 mp4 提取帧到 jpg 格式会产生错误

    我正在尝试使用 ffmpeg 从 mp4 视频中提取所有帧 我使用以下命令 ffmpeg i Users raimundbuehler recordings 2022 01 24 000 exports 001 world mp4 vsyn
  • Jersey 客户端 API 中的内容 MD5

    我正在尝试在使用 Jersey Client API 创建的请求上设置 Content MD5 标头 我创建了 ClientFilter 它实现了另一个适配器 类似于 GZipFilter 的工作方式 像这样 public class Co