diff --git a/CHANGELOG.md b/CHANGELOG.md index 14f0e56..1cb6e81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ BUG FIXES - Fixed `encode_path` incorrectly encoding hyphens (`-`), which caused 403 errors on Vault 1.15+ [GH-350, GH-343] - Fixed `FrozenError` when loading the gem with OpenSSL 4.0.0+ by removing modification of `OpenSSL::SSL::SSLContext::DEFAULT_PARAMS`. Modern Ruby (3.1+) already has secure SSL defaults. [GH-366, GH-381] +- Fixed `Vault.logical.read` throwing `NoMethodError` when Vault responds with HTTP 204 (No Content). Now correctly returns `nil` for empty responses. [GH-241] ## v0.19.0 (December 3, 2025) diff --git a/lib/vault/api/logical.rb b/lib/vault/api/logical.rb index c1120de..9e9234d 100644 --- a/lib/vault/api/logical.rb +++ b/lib/vault/api/logical.rb @@ -48,6 +48,7 @@ def list(path, options = {}) def read(path, options = {}) headers = extract_headers!(options) json = client.get("/v1/#{encode_path(path)}", {}, headers) + return nil if json.nil? return Secret.decode(json) rescue HTTPError => e return nil if e.code == 404 diff --git a/spec/unit/logical_spec.rb b/spec/unit/logical_spec.rb new file mode 100644 index 0000000..e9e78d2 --- /dev/null +++ b/spec/unit/logical_spec.rb @@ -0,0 +1,50 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +require "spec_helper" + +module Vault + describe Logical do + let(:client) { double("client") } + subject { described_class.new(client) } + + describe "#read" do + it "returns nil when client.get returns nil (HTTP 204 No Content)" do + allow(client).to receive(:get).and_return(nil) + + result = subject.read("pki/ca") + + expect(result).to be_nil + end + + it "returns a Secret when client.get returns data" do + allow(client).to receive(:get).and_return({ + data: { foo: "bar" }, + lease_duration: 0, + renewable: false + }) + + result = subject.read("secret/test") + + expect(result).to be_a(Secret) + expect(result.data).to eq(foo: "bar") + end + + it "returns nil when client.get raises HTTPError with 404" do + allow(client).to receive(:get).and_raise(HTTPError.new("address", double(code: "404"))) + + result = subject.read("secret/missing") + + expect(result).to be_nil + end + + it "raises HTTPError for other error codes" do + allow(client).to receive(:get).and_raise(HTTPError.new("address", double(code: "500"))) + + expect { + subject.read("secret/error") + }.to raise_error(HTTPError) + end + end + end +end