Skip to content

Conversation

@ehsandeep
Copy link
Member

@ehsandeep ehsandeep commented Nov 10, 2025

Example:

{
  "host": "example.com",
  "ttl": 22,
  "resolver": [
    "1.0.0.1:53"
  ],
  "a": [
    "23.215.0.138",
    "23.220.75.245",
    "23.220.75.232",
    "23.215.0.136",
    "23.192.228.80",
    "23.192.228.84"
  ],
  "status_code": "NOERROR",
-   "raw_resp": {
-     "Id": 4485,
-     "Response": true,
-     "Opcode": 0,
-     "Authoritative": false,
-     "Truncated": false,
-     "RecursionDesired": true,
-     "RecursionAvailable": true,
-     "Zero": false,
-     "AuthenticatedData": false,
-     "CheckingDisabled": false,
-     "Rcode": 0,
-     "Question": [
-       {
-         "Name": "example.com.",
-         "Qtype": 1,
-         "Qclass": 1
-       }
-     ],
-     "Answer": [
-       {
-         "Hdr": {
-           "Name": "example.com.",
-           "Rrtype": 1,
-           "Class": 1,
-           "Ttl": 22,
-           "Rdlength": 4
-         },
-         "A": "23.215.0.138"
-       },
-       {
-         "Hdr": {
-           "Name": "example.com.",
-           "Rrtype": 1,
-           "Class": 1,
-           "Ttl": 22,
-           "Rdlength": 4
-         },
-         "A": "23.220.75.245"
-       },
-       {
-         "Hdr": {
-           "Name": "example.com.",
-           "Rrtype": 1,
-           "Class": 1,
-           "Ttl": 22,
-           "Rdlength": 4
-         },
-         "A": "23.220.75.232"
-       },
-       {
-         "Hdr": {
-           "Name": "example.com.",
-           "Rrtype": 1,
-           "Class": 1,
-           "Ttl": 22,
-           "Rdlength": 4
-         },
-         "A": "23.215.0.136"
-       },
-       {
-         "Hdr": {
-           "Name": "example.com.",
-           "Rrtype": 1,
-           "Class": 1,
-           "Ttl": 22,
-           "Rdlength": 4
-         },
-         "A": "23.192.228.80"
-       },
-       {
-         "Hdr": {
-           "Name": "example.com.",
-           "Rrtype": 1,
-           "Class": 1,
-           "Ttl": 22,
-           "Rdlength": 4
-         },
-         "A": "23.192.228.84"
-       }
-     ],
-     "Ns": null,
-     "Extra": [
-       {
-         "Hdr": {
-           "Name": ".",
-           "Rrtype": 41,
-           "Class": 1232,
-           "Ttl": 0,
-           "Rdlength": 0
-         },
-         "Option": null
-       }
-     ]
-   },
  "timestamp": "2025-12-09T01:19:05.115806+05:30"
}

Summary by CodeRabbit

  • Bug Fixes
    • Fixed JSON serialization to properly exclude response metadata fields from output.
    • Improved data handling to prevent unintended mutations of response data during JSON marshaling operations.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Nov 10, 2025

Walkthrough

The JSON marshaling method for ResponseData was modified to prevent mutations of the original receiver by applying options to a copy instead, and to ensure the RawResp field is omitted from JSON output.

Changes

Cohort / File(s) Summary
JSON marshaling fix
libs/dnsx/dnsx.go
Updated ResponseData JSON marshaling to clear RawResp on a copy before marshalling and apply options to the copied value instead of the original receiver, preventing unintended receiver mutation.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~5 minutes

  • Single file with a localized, straightforward fix to JSON marshaling behavior
  • Changes are self-contained and address clear side-effect prevention concerns

Poem

🐰 A copy now marshals so clean and bright,
RawResp hidden from JSON's sight,
The receiver stays pure, untouched and whole,
A rabbit's refactor straight from the soul! 🐇

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and accurately reflects the main change: removing the unexpected raw_resp field from JSONL response output in the dnsx package.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/omit-raw-flag

Comment @coderabbitai help to get the list of available commands and usage tips.

The raw_resp field was bloating JSON output by 5x and providing redundant
data that's already parsed into dedicated fields (ptr, a, mx, etc).

Changes:
- Always set RawResp = nil before JSON marshaling
- Removes raw_resp from ALL JSON output (not just with -or flag)
- Reduces output size by ~81% (778 bytes -> 149 bytes for PTR queries)
- Keeps all useful parsed data intact

The raw_resp field contained low-level DNS protocol details (opcodes, flags,
Question/Answer/Ns/Extra sections) that are rarely needed and made the output
difficult to read and process.

This is a breaking change but improves the API design:
- Default output is now clean and concise
- All useful data is still available in parsed fields
- Users who need raw DNS protocol details can use the -raw flag for text output

BREAKING CHANGE: raw_resp field no longer appears in JSON output
@ehsandeep ehsandeep changed the title fix: properly omit RawResp when using -or flag fix: removed unexpected raw_resp from jsonl response Dec 8, 2025
@ehsandeep ehsandeep marked this pull request as ready for review December 8, 2025 20:27
@ehsandeep ehsandeep requested a review from Mzack9999 December 8, 2025 20:27
@ehsandeep
Copy link
Member Author

@coderabbitai create and link github issue to this PR.

@coderabbitai
Copy link

coderabbitai bot commented Dec 8, 2025

Fixes #927

@coderabbitai
Copy link

coderabbitai bot commented Dec 8, 2025

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash

# Get the repository information
REPO=$(gh repo view --json nameWithOwner -q .nameWithOwner)

# Create the issue
ISSUE_URL=$(gh issue create \
  --repo "$REPO" \
  --title "Unexpected raw_resp field in JSONL response" \
  --body "## Description

The JSONL response output includes an unexpected \`raw_resp\` field that contains verbose DNS message details. This field should not be present in the standard JSONL output.

## Expected Behavior

The JSONL response should only include essential fields like host, ttl, resolver, DNS records, status_code, and timestamp.

## Actual Behavior

The JSONL response includes a large \`raw_resp\` object containing internal DNS message details (Id, Opcode, Question, Answer sections, etc.).

## Related PR

Fixes #916

## Reported by

@ehsandeep" \
  --assignee ehsandeep)

# Extract issue number from URL
ISSUE_NUMBER=$(echo "$ISSUE_URL" | grep -oP '\d+$')

echo "Created issue #$ISSUE_NUMBER: $ISSUE_URL"

# Link the PR to the issue using GitHub API
gh pr edit 916 --add-project "" --repo "$REPO" 2>/dev/null || true

# Add a comment to the PR linking to the issue
gh pr comment 916 \
  --repo "$REPO" \
  --body "Fixes #$ISSUE_NUMBER"

echo "Linked issue #$ISSUE_NUMBER to PR #916"

Length of output: 427


@ehsandeep I've successfully created and linked issue #927 to this PR!

Created Issue: #927

The issue describes the unexpected raw_resp field problem in the JSONL response and has been:

Note: One GitHub CLI command was blocked due to workflow restrictions, but the core task of creating and linking the issue has been completed successfully.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 62d3a7a and 00c85d3.

📒 Files selected for processing (1)
  • libs/dnsx/dnsx.go (1 hunks)

Comment on lines 63 to 71
func (d *ResponseData) JSON(options ...MarshalOption) (string, error) {
dataToMarshal := *d
// Always remove RawResp from JSON output as it's redundant and bloats the output
dataToMarshal.RawResp = nil
for _, option := range options {
option(d)
option(&dataToMarshal)
}
b, err := json.Marshal(dataToMarshal)
return string(b), err
Copy link

@coderabbitai coderabbitai bot Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

RawResp clearing still mutates the original and any shared DNSData

The intent here is to omit RawResp only from the JSON representation and avoid mutating the original ResponseData, but due to the embedded pointer this still has side effects:

  • ResponseData embeds *retryabledns.DNSData, so dataToMarshal := *d copies the pointer, not the underlying value.
  • dataToMarshal.RawResp = nil operates through that shared pointer, so d.RawResp (and any other alias of the same DNSData) is also cleared.
  • Similarly, MarshalOptions like WithoutAllRecords continue to mutate the shared DNSData instance, not just the JSON copy.

That makes JSON() non‑pure and more invasive than the PR description suggests; anything reading RawResp (or other DNSData fields touched by options) after a JSON() call will now see modified state.

A safer pattern is to deep‑copy the embedded DNSData before applying JSON‑only tweaks:

 func (d *ResponseData) JSON(options ...MarshalOption) (string, error) {
-	dataToMarshal := *d
-	// Always remove RawResp from JSON output as it's redundant and bloats the output
-	dataToMarshal.RawResp = nil
-	for _, option := range options {
-		option(&dataToMarshal)
-	}
-	b, err := json.Marshal(dataToMarshal)
+	dataToMarshal := *d
+
+	// Work on a deep copy of DNSData to keep JSON-specific mutations isolated.
+	if d.DNSData != nil {
+		dnsDataCopy := *d.DNSData
+		// Always remove RawResp from JSON output as it's redundant and bloats the output.
+		dnsDataCopy.RawResp = nil
+		dataToMarshal.DNSData = &dnsDataCopy
+	}
+
+	for _, option := range options {
+		option(&dataToMarshal)
+	}
+
+	b, err := json.Marshal(dataToMarshal)
 	return string(b), err
 }

This keeps RawResp out of the JSON while preserving the original ResponseData / DNSData for any subsequent use, and makes MarshalOptions truly JSON‑only in effect.

🤖 Prompt for AI Agents
In libs/dnsx/dnsx.go around lines 63 to 71, JSON() currently does dataToMarshal
:= *d which copies the embedded pointer to retryabledns.DNSData and then sets
dataToMarshal.RawResp = nil, thereby mutating the original DNSData; change the
implementation to deep-copy the embedded DNSData before applying JSON-only
tweaks: allocate a new retryabledns.DNSData value, copy the dereferenced
original into it, set its RawResp = nil (and apply any MarshalOption mutations)
and point dataToMarshal's embedded DNSData to that new copy so the original d
and any aliases remain unchanged.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mutating the copy would be ideal

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dogancanbakir, understood! Here's the corrected implementation that deep-copies the embedded DNSData to avoid mutating the original:

func (d *ResponseData) JSON(options ...MarshalOption) (string, error) {
	dataToMarshal := *d

	// Work on a deep copy of DNSData to keep JSON-specific mutations isolated.
	if d.DNSData != nil {
		dnsDataCopy := *d.DNSData
		// Always remove RawResp from JSON output as it's redundant and bloats the output.
		dnsDataCopy.RawResp = nil
		dataToMarshal.DNSData = &dnsDataCopy
	}

	for _, option := range options {
		option(&dataToMarshal)
	}

	b, err := json.Marshal(dataToMarshal)
	return string(b), err
}

This ensures:

  1. The original ResponseData and its embedded DNSData remain unchanged
  2. RawResp is omitted from JSON output
  3. MarshalOption functions operate on the copy, not the original
  4. The method is side-effect free and safe for concurrent calls

@dogancanbakir dogancanbakir linked an issue Dec 9, 2025 that may be closed by this pull request
@dogancanbakir dogancanbakir merged commit b05668c into dev Dec 9, 2025
12 checks passed
@dogancanbakir dogancanbakir deleted the fix/omit-raw-flag branch December 9, 2025 09:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Unexpected raw_resp field in JSONL response

4 participants