JSON API for DNS queries #1292

Open
opened 2026-03-04 01:12:11 -05:00 by deekerman · 4 comments
Owner

Originally created by @zhaokelei on GitHub (Feb 5, 2020).

How to view resolution requests for a single domain name?

Querying domain name system data in JSON format

such as

curl -H 'accept: application/dns-json' 'https://cloudflare-dns.com/dns-query?name=example.com&type=AAAA'

Originally created by @zhaokelei on GitHub (Feb 5, 2020). How to view resolution requests for a single domain name? Querying domain name system data in JSON format such as curl -H 'accept: application/dns-json' 'https://cloudflare-dns.com/dns-query?name=example.com&type=AAAA'
Author
Owner

@ameshkov commented on GitHub (Feb 5, 2020):

Would you like to have JSON API like this one or are you asking how to send a DNS request to a DOH resolver?

If you'd like to send a DNS query, you can use this https://github.com/ameshkov/dnslookup

@ameshkov commented on GitHub (Feb 5, 2020): Would you like to have JSON API like this one or are you asking how to send a DNS request to a DOH resolver? If you'd like to send a DNS query, you can use this https://github.com/ameshkov/dnslookup
Author
Owner

@zhaokelei commented on GitHub (Feb 5, 2020):

I'd like to use json api

@zhaokelei commented on GitHub (Feb 5, 2020): I'd like to use json api
Author
Owner

@ZeroClover commented on GitHub (Oct 29, 2020):

I also hope to be able to implement the JSON API.

Some of my DNS servers use a pound of programs such as DoH Server and Unbound to implement the functions of AdGuard Home. I hope to replace it with AGH, but it is best to support all the previous functions fully.

Another outdated DoH clients also only support JSON format and no DNS wireformat.

@ZeroClover commented on GitHub (Oct 29, 2020): I also hope to be able to implement the JSON API. Some of my DNS servers use a pound of programs such as DoH Server and Unbound to implement the functions of AdGuard Home. I hope to replace it with AGH, but it is best to support all the previous functions fully. Another outdated DoH clients also only support JSON format and no DNS wireformat.
Author
Owner

@1265578519 commented on GitHub (May 8, 2023):

都2023年了,什么这软件还不支持json?
https://dns.google/resolve?ct=application/dns-json&name=www.baidu.com.&type=A&edns_client_subnet=0.0.0.0/0

cf workers
https://diii.tk/https://dns.google/resolve?ct=application/dns-json&name=www.baidu.com.&type=A&edns_client_subnet=0.0.0.0/0

addEventListener('fetch', event => {
    event.passThroughOnException()
  
    event.respondWith(handleRequest(event))
  })
  
  /**
  * Respond to the request
  * @param {Request} request
  */
  async function handleRequest(event) {
    const { request } = event;
  
    //请求头部、返回对象
    let reqHeaders = new Headers(request.headers),
        outBody, outStatus = 200, outStatusText = 'OK', outCt = null, outHeaders = new Headers({
            "Access-Control-Allow-Origin": reqHeaders.get('Origin'),
            "Access-Control-Allow-Methods": "GET, POST, PUT, PATCH, DELETE, OPTIONS",
            "Access-Control-Allow-Headers": reqHeaders.get('Access-Control-Allow-Headers') || "Accept, Authorization, Cache-Control, Content-Type, DNT, If-Modified-Since, Keep-Alive, Origin, User-Agent, X-Requested-With, Token, x-access-token, Notion-Version"
        });
  
    try {
        //取域名第一个斜杠后的所有信息为代理链接
        let url = request.url.substr(8);
        url = decodeURIComponent(url.substr(url.indexOf('/') + 1));
  
        //需要忽略的代理
        if (request.method == "OPTIONS" && reqHeaders.has('access-control-request-headers')) {
            //输出提示
            return new Response(null, PREFLIGHT_INIT)
        }
        else if(url.length < 3 || url.indexOf('.') == -1 || url == "favicon.ico" || url == "robots.txt") {
            return Response.redirect('https://baidu.com', 301)
        }
        //阻断
        else if (blocker.check(url)) {
            return Response.redirect('https://baidu.com', 301)
        }
        else {
            //补上前缀 http://
            url = url.replace(/https:(\/)*/,'https://').replace(/http:(\/)*/, 'http://')
            if (url.indexOf("://") == -1) {
                url = "http://" + url;
            }
            //构建 fetch 参数
            let fp = {
                method: request.method,
                headers: {}
            }
  
            //保留头部其它信息
            let he = reqHeaders.entries();
            for (let h of he) {
                if (!['content-length'].includes(h[0])) {
                    fp.headers[h[0]] = h[1];
                }
            }
            // 是否带 body
            if (["POST", "PUT", "PATCH", "DELETE"].indexOf(request.method) >= 0) {
                const ct = (reqHeaders.get('content-type') || "").toLowerCase();
                if (ct.includes('application/json')) {
                      let requestJSON = await request.json()
                      console.log(typeof requestJSON)
                    fp.body = JSON.stringify(requestJSON);
                } else if (ct.includes('application/text') || ct.includes('text/html')) {
                    fp.body = await request.text();
                } else if (ct.includes('form')) {
                    fp.body = await request.formData();
                } else {
                    fp.body = await request.blob();
                }
            }
            // 发起 fetch
            let fr = (await fetch(url, fp));
            outCt = fr.headers.get('content-type');
            if(outCt && (outCt.includes('application/text') || outCt.includes('text/html'))) {
              try {
                // 添加base
                let newFr = new HTMLRewriter()
                .on("head", {
                  element(element) {
                    element.prepend(`<base href="${url}" />`, {
                      html: true
                    })
                  },
                })
                .transform(fr)
                fr = newFr
              } catch(e) {
              }
            }

            for (const [key, value] of fr.headers.entries()) {
              outHeaders.set(key, value);
            }

            outStatus = fr.status;
            outStatusText = fr.statusText;
            outBody = fr.body;
        }
    } catch (err) {
        outCt = "application/json";
        outBody = JSON.stringify({
            code: -1,
            msg: JSON.stringify(err.stack) || err
        });
    }
  
    //设置类型
    if (outCt && outCt != "") {
        outHeaders.set("content-type", outCt);
    }
  
    let response = new Response(outBody, {
        status: outStatus,
        statusText: outStatusText,
        headers: outHeaders
    })
  
    return response;
  
    // return new Response('OK', { status: 200 })
  }
  
  /**
  * 阻断器
  */
  const blocker = {
    keys: [".m3u8", ".ts", ".acc", ".m4s", "photocall.tv", "googlevideo.com"],
    check: function (url) {
        url = url.toLowerCase();
        let len = blocker.keys.filter(x => url.includes(x)).length;
        return len != 0;
    }
  }
@1265578519 commented on GitHub (May 8, 2023): 都2023年了,什么这软件还不支持json? https://dns.google/resolve?ct=application/dns-json&name=www.baidu.com.&type=A&edns_client_subnet=0.0.0.0/0 cf workers https://diii.tk/https://dns.google/resolve?ct=application/dns-json&name=www.baidu.com.&type=A&edns_client_subnet=0.0.0.0/0 ``` addEventListener('fetch', event => { event.passThroughOnException() event.respondWith(handleRequest(event)) }) /** * Respond to the request * @param {Request} request */ async function handleRequest(event) { const { request } = event; //请求头部、返回对象 let reqHeaders = new Headers(request.headers), outBody, outStatus = 200, outStatusText = 'OK', outCt = null, outHeaders = new Headers({ "Access-Control-Allow-Origin": reqHeaders.get('Origin'), "Access-Control-Allow-Methods": "GET, POST, PUT, PATCH, DELETE, OPTIONS", "Access-Control-Allow-Headers": reqHeaders.get('Access-Control-Allow-Headers') || "Accept, Authorization, Cache-Control, Content-Type, DNT, If-Modified-Since, Keep-Alive, Origin, User-Agent, X-Requested-With, Token, x-access-token, Notion-Version" }); try { //取域名第一个斜杠后的所有信息为代理链接 let url = request.url.substr(8); url = decodeURIComponent(url.substr(url.indexOf('/') + 1)); //需要忽略的代理 if (request.method == "OPTIONS" && reqHeaders.has('access-control-request-headers')) { //输出提示 return new Response(null, PREFLIGHT_INIT) } else if(url.length < 3 || url.indexOf('.') == -1 || url == "favicon.ico" || url == "robots.txt") { return Response.redirect('https://baidu.com', 301) } //阻断 else if (blocker.check(url)) { return Response.redirect('https://baidu.com', 301) } else { //补上前缀 http:// url = url.replace(/https:(\/)*/,'https://').replace(/http:(\/)*/, 'http://') if (url.indexOf("://") == -1) { url = "http://" + url; } //构建 fetch 参数 let fp = { method: request.method, headers: {} } //保留头部其它信息 let he = reqHeaders.entries(); for (let h of he) { if (!['content-length'].includes(h[0])) { fp.headers[h[0]] = h[1]; } } // 是否带 body if (["POST", "PUT", "PATCH", "DELETE"].indexOf(request.method) >= 0) { const ct = (reqHeaders.get('content-type') || "").toLowerCase(); if (ct.includes('application/json')) { let requestJSON = await request.json() console.log(typeof requestJSON) fp.body = JSON.stringify(requestJSON); } else if (ct.includes('application/text') || ct.includes('text/html')) { fp.body = await request.text(); } else if (ct.includes('form')) { fp.body = await request.formData(); } else { fp.body = await request.blob(); } } // 发起 fetch let fr = (await fetch(url, fp)); outCt = fr.headers.get('content-type'); if(outCt && (outCt.includes('application/text') || outCt.includes('text/html'))) { try { // 添加base let newFr = new HTMLRewriter() .on("head", { element(element) { element.prepend(`<base href="${url}" />`, { html: true }) }, }) .transform(fr) fr = newFr } catch(e) { } } for (const [key, value] of fr.headers.entries()) { outHeaders.set(key, value); } outStatus = fr.status; outStatusText = fr.statusText; outBody = fr.body; } } catch (err) { outCt = "application/json"; outBody = JSON.stringify({ code: -1, msg: JSON.stringify(err.stack) || err }); } //设置类型 if (outCt && outCt != "") { outHeaders.set("content-type", outCt); } let response = new Response(outBody, { status: outStatus, statusText: outStatusText, headers: outHeaders }) return response; // return new Response('OK', { status: 200 }) } /** * 阻断器 */ const blocker = { keys: [".m3u8", ".ts", ".acc", ".m4s", "photocall.tv", "googlevideo.com"], check: function (url) { url = url.toLowerCase(); let len = blocker.keys.filter(x => url.includes(x)).length; return len != 0; } } ```
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/AdGuardHome#1292
No description provided.