mirror of https://gitlab.com/hrbrmstr/playdoh.git
13 changed files with 215 additions and 174 deletions
@ -1,6 +1,6 @@ |
|||
# Generated by roxygen2: do not edit by hand |
|||
|
|||
export(doh_post) |
|||
export(doh_get) |
|||
export(doh_servers) |
|||
import(httr) |
|||
import(reticulate) |
|||
importFrom(jsonlite,fromJSON) |
|||
|
@ -0,0 +1,7 @@ |
|||
httr::user_agent( |
|||
sprintf( |
|||
"playdoh package v%s: (<%s>)", |
|||
utils::packageVersion("playdoh"), |
|||
utils::packageDescription("playdoh")$URL |
|||
) |
|||
) -> .PLAYDOH_UA |
@ -0,0 +1,51 @@ |
|||
#' Make a DoH Request (GET/REST) |
|||
#' |
|||
#' Issue a `GET` REST API query of type `type` for `name` to the |
|||
#' DoH endpoint specified at `server_path`. |
|||
#' |
|||
#' @param name name to query for |
|||
#' @param type DNS query type (defaults to "`A`") |
|||
#' @param server_path full URL path to the DoH server quer endpoint (defaults to Quad9). |
|||
#' @param extra_params any special `GET` query parameter needed for a given server API endpoint. |
|||
#' this should be a named `list`. |
|||
#' @return `NULL` (if the query failed) or a `data.frame` (tibble) |
|||
#' @references <https://tools.ietf.org/id/draft-ietf-doh-dns-over-https-05.html> |
|||
#' @export |
|||
#' @examples |
|||
#' doh_get("rud.is", "A") |
|||
doh_get <- function(name, type = "a", extra_params = list(), service_path = "https://9.9.9.9/dns-query") { |
|||
|
|||
stopifnot(is.list(extra_params)) |
|||
|
|||
extra_params[["name"]] <- tolower(name) |
|||
extra_params[["type"]] <- tolower(type[1]) |
|||
|
|||
httr::GET( |
|||
url = service_path, |
|||
query = extra_params, |
|||
.PLAYDOH_UA |
|||
) -> res |
|||
|
|||
httr::stop_for_status(res) |
|||
|
|||
out <- httr::content(res, as = "text", encoding = "UTF-8") |
|||
out <- jsonlite::fromJSON(out) |
|||
|
|||
# will be NULL or a data frame |
|||
ret <- out[["Answer"]] |
|||
|
|||
# cleanup column names and add query metadata if query was OK |
|||
if (length(ret)) { |
|||
|
|||
colnames(ret) <- tolower(colnames(ret)) |
|||
|
|||
attr(ret, "question") <- out[["Question"]] |
|||
attr(ret, "flags") <- out[c("Status", "TC", "RD", "RA", "AD", "CD")] |
|||
attr(ret, "edns_client_subnet") <- out[["edns_client_subnet"]] |
|||
attr(ret, "comment") <- out[["comment"]] |
|||
|
|||
} |
|||
|
|||
ret |
|||
|
|||
} |
@ -1,70 +0,0 @@ |
|||
#' Make a POST DoH Request (wireformat) |
|||
#' |
|||
#' Issue the query of type `type` for `name` to the DoH endpoint specified at `server_path`. |
|||
#' |
|||
#' @param name name to query for |
|||
#' @param type DNS query type (defaults to "`A`") |
|||
#' @param server_path full URL path to the DoH server quer endpoint (defaults to Quad9). |
|||
#' @return `NULL` (if the query failed) or a `data.frame` (tibble) |
|||
#' @references <https://tools.ietf.org/id/draft-ietf-doh-dns-over-https-05.html> |
|||
#' @export |
|||
doh_post <- function(name, type = "A", server_path = "https://dns.quad9.net/dns-query") { |
|||
|
|||
# for now, use python's {dnslib} as a crutch to |
|||
# encode/decode wireformat DNS questions and answers |
|||
|
|||
.dns$DNSRecord$question( |
|||
qname = tolower(name[1]), |
|||
qtype = toupper(type[1]), |
|||
qclass = "IN" |
|||
) -> q |
|||
|
|||
qpak <- q$pack() |
|||
|
|||
# now, send it off to the server |
|||
|
|||
httr::POST( |
|||
url = server_path[1], |
|||
httr::add_headers( |
|||
`Content-Type` = "application/dns-message", |
|||
`Accept` = "application/dns-message" |
|||
), |
|||
encode = "raw", |
|||
body = qpak |
|||
) -> res |
|||
|
|||
httr::warn_for_status(res) |
|||
|
|||
# if the response is OK, make it a data frame |
|||
|
|||
if (httr::status_code(res) == 200) { |
|||
|
|||
r <- .dns$DNSRecord$parse(httr::content(res)) |
|||
|
|||
q <- r$get_q() |
|||
|
|||
do.call( |
|||
rbind.data.frame, |
|||
lapply(r$rr, function(.x) { |
|||
data.frame( |
|||
query = py_str(q$qname), |
|||
qtype = q$qtype, |
|||
rname = py_str(.x$rname), |
|||
rtype = .x$rtype, |
|||
rdata = py_str(.x$rdata), |
|||
ttl = .x$ttl, |
|||
stringsAsFactors = FALSE |
|||
) |
|||
}) |
|||
|
|||
) -> xdf |
|||
|
|||
class(xdf) <- c("tbl_df", "tbl", "data.frame") |
|||
|
|||
xdf |
|||
|
|||
} else { |
|||
NULL |
|||
} |
|||
|
|||
} |
@ -1,29 +0,0 @@ |
|||
py_c <- reticulate::py_config() |
|||
|
|||
.dns <- NULL |
|||
|
|||
.onLoad <- function(libname, pkgname) { |
|||
|
|||
if (utils::compareVersion(py_c$version, "3.5") < 0) { |
|||
stop( |
|||
paste0( |
|||
c( |
|||
"Python 3.5+ is required. If this is installed please set RETICULATE_PYTHON ", |
|||
"to the path to the Python 3 binary on your system and try re-installing/", |
|||
"re-loading the package." |
|||
), |
|||
collapse = "" |
|||
) |
|||
) |
|||
return() |
|||
} |
|||
|
|||
if (!reticulate::py_module_available("dnslib")) { |
|||
packageStartupMessage( |
|||
"The 'dnslib' Python module must be installed." |
|||
) |
|||
} else { |
|||
.dns <<- reticulate::import("dnslib", delay_load = TRUE) |
|||
} |
|||
|
|||
} |
@ -0,0 +1,32 @@ |
|||
% Generated by roxygen2: do not edit by hand |
|||
% Please edit documentation in R/doh-get.R |
|||
\name{doh_get} |
|||
\alias{doh_get} |
|||
\title{Make a DoH Request (GET/REST)} |
|||
\usage{ |
|||
doh_get(name, type = "a", extra_params = list(), |
|||
service_path = "https://9.9.9.9/dns-query") |
|||
} |
|||
\arguments{ |
|||
\item{name}{name to query for} |
|||
|
|||
\item{type}{DNS query type (defaults to "\code{A}")} |
|||
|
|||
\item{extra_params}{any special \code{GET} query parameter needed for a given server API endpoint. |
|||
this should be a named \code{list}.} |
|||
|
|||
\item{server_path}{full URL path to the DoH server quer endpoint (defaults to Quad9).} |
|||
} |
|||
\value{ |
|||
\code{NULL} (if the query failed) or a \code{data.frame} (tibble) |
|||
} |
|||
\description{ |
|||
Issue a \code{GET} REST API query of type \code{type} for \code{name} to the |
|||
DoH endpoint specified at \code{server_path}. |
|||
} |
|||
\examples{ |
|||
doh_get("rud.is", "A") |
|||
} |
|||
\references{ |
|||
\url{https://tools.ietf.org/id/draft-ietf-doh-dns-over-https-05.html} |
|||
} |
@ -1,25 +0,0 @@ |
|||
% Generated by roxygen2: do not edit by hand |
|||
% Please edit documentation in R/doh-post.R |
|||
\name{doh_post} |
|||
\alias{doh_post} |
|||
\title{Make a POST DoH Request (wireformat)} |
|||
\usage{ |
|||
doh_post(name, type = "A", |
|||
server_path = "https://dns.quad9.net/dns-query") |
|||
} |
|||
\arguments{ |
|||
\item{name}{name to query for} |
|||
|
|||
\item{type}{DNS query type (defaults to "\code{A}")} |
|||
|
|||
\item{server_path}{full URL path to the DoH server quer endpoint (defaults to Quad9).} |
|||
} |
|||
\value{ |
|||
\code{NULL} (if the query failed) or a \code{data.frame} (tibble) |
|||
} |
|||
\description{ |
|||
Issue the query of type \code{type} for \code{name} to the DoH endpoint specified at \code{server_path}. |
|||
} |
|||
\references{ |
|||
\url{https://tools.ietf.org/id/draft-ietf-doh-dns-over-https-05.html} |
|||
} |
@ -0,0 +1,27 @@ |
|||
% Generated by roxygen2: do not edit by hand |
|||
% Please edit documentation in R/globals.R |
|||
\docType{data} |
|||
\name{doh_servers} |
|||
\alias{doh_servers} |
|||
\title{Built-in list of DoH Servers} |
|||
\format{An object of class \code{list} of length 6.} |
|||
\usage{ |
|||
doh_servers |
|||
} |
|||
\description{ |
|||
The \code{url} element has the URL for the \code{GET} requests and |
|||
the \code{extra_params} element has any needed query parameters |
|||
for the \code{GET} requests. |
|||
} |
|||
\details{ |
|||
The list so far. |
|||
\itemize{ |
|||
\item \code{google}: \url{https://dns.google.com/experimental} |
|||
\item \code{cloudflare}: \url{https://cloudflare-dns.com/dns-query} |
|||
\item \code{quad9}: \url{https://dns.quad9.net/dns-query} |
|||
\item \code{securedns_eu}: \url{https://doh.securedns.eu/dns-query} |
|||
\item \code{dnswarden_adblock}: \url{https://doh.dnswarden.com/adblock} |
|||
\item \code{dnswarden_uncensored}: \url{https://doh.dnswarden.com/uncensored} |
|||
} |
|||
} |
|||
\keyword{datasets} |
Loading…
Reference in new issue