1

I always getting the same error (Create domain 'example.com' failed) (or any domain) when trying to create new DNS zone with Powerdns API call.

My request:

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,'http://127.0.0.1:953/api/v1/servers/localhost/zones');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "{\"name\":\"example.com.\", \"kind\":\"Native\", \"masters\": [], \"nameservers\":[\"ns1.example.com.\", \"ns2.example.com.\"]}");
$headers = array();
$headers[] = 'X-Api-Key: MY-KEY';
$headers[] = 'Accept: application/json';
$headers[] = 'Content-Type: application/json';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close($ch);

Similar api call to get a list of DNS zones is working. GET request work properly but not POST. Can anyone help, please?

My pdns.conf file is:

api=yes
api-key=MY-KEY

Maybe i have to change something in settings of my powerdns, idk really. I would be very grateful for any help!

Server response after POST request is 422 error (Unprocessable Entity)

HTTP/1.1 422 Unprocessable Entity Access-Control-Allow-Origin: * Connection: close Content-Length: 52 Content-Security-Policy: default-src 'self'; style-src 'self' 'unsafe-inline' Content-Type: application/json Server: PowerDNS/4.4.1 X-Content-Type-Options: nosniff X-Frame-Options: deny X-Permitted-Cross-Domain-Policies: none X-Xss-Protection: 1; mode=block

This is my pdns.conf file
cat /etc/pdns/pdns.conf
bind-ignore-broken-records=yes
setuid=named
setgid=named
launch=bind
log-dns-queries=yes
loglevel=5
bind-config=/etc/named.conf
bind-dnssec-db=/var/cpanel/pdns/dnssec.db
local-address-nonexist-fail=no
distributor-threads=1
disable-axfr=yes
webserver=yes
api=yes
webserver-address=127.0.0.1
webserver-allow-from=0.0.0.0/0
webserver-password=SERVER-KEY
#gmysql-dnssec=no
webserver-port=953
api-key=MY-KEY
upgrade-unknown-types=1
9
  • Did you look at your server logfiles, as they may give more information on what was wrong? Commented Sep 5, 2022 at 17:19
  • Yes it is return 422 error myserver pdns_server[138302]: [webserver] affd4b0a-67ab-4d57-84ec-112a017a3002 127.0.0.1:46800 "POST /api/v1/servers/localhost/zones HTTP/1.1" 422 420 Something like this @PatrickMevzek "Unprocessable Entity" Error 422 Commented Sep 5, 2022 at 17:29
  • 422 means the input is not accepted because malformed. I would take inspiration from stackoverflow.com/a/60304664/6368697 on how to properly pass the JSON structure and in a far simpler way with json_encode otherwise manually you need to encode part of the content. The content-type header is also probably mandatory. Otherwise I would recommend you use GET to retrieve current zones (create one manually outside of the API) so that you have clear examples of structures to use, and you can reuse them during POST. Commented Sep 5, 2022 at 19:00
  • I don't have any way to test this, but I assume the problem is because you forgot to include the Content-Type request header. Commented Sep 5, 2022 at 19:56
  • Logging the response body may provide a more specific error message. Commented Sep 5, 2022 at 19:58

2 Answers 2

1

Your code looks correct.

One big problem with your response.
Content-Length: 52
It should be Content-Length: 111.

I have been testing your code with two apps
One to send the curl request
One to receive it and respond with the request details.

Early on in my testing when I removed the Content-Type: application/json, I would see a content length of just over 50 bytes.

Below is my app. It gets 111 bytes.
If you change your curl url to http://eatled.com/receiveheader.php
You should get this:

Response
Content-Length: 111
Content-Type: application/json
Accept: application/json
Accept-Encoding: deflate, gzip, br
Host: eatled.com
X-Api-Key: MY-KEY

BODY

{"name":"example.com.", "kind":"Native", "masters": [], "nameservers":["ns1.example.com.", "ns2.example.com."]}


array (
  'name' => 'example.com.',
  'kind' => 'Native',
  'masters' => 
  array (
  ),
  'nameservers' => 
  array (
    0 => 'ns1.example.com.',
    1 => 'ns2.example.com.',
  ),
)

LINK TO MY CURL SANDBOX

The source code:
sandbox.php

<?php
header('Content-Type: text/plain; charset=UTF-8');
$jsn = "{\"name\":\"example.com.\", \"kind\":\"Native\", \"masters\": [], \"nameservers\":[\"ns1.example.com.\", \"ns2.example.com.\"]}";
$data = json_decode($post,1);
$post = $jsn;
$request = array();
$request[] = "Content-Type: application/json";
$request[] = "Accept: application/json";
$request[] = "X-Api-Key: MY-KEY";
$ch = curl_init();
curl_setopt($ch, CURLOPT_HTTPHEADER, $request);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);    
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);   
curl_setopt($ch, CURLOPT_URL, 'http://eatled.com/receiveheader.php'); 
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_TIMEOUT,10);
curl_setopt($ch, CURLOPT_FAILONERROR,true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_ENCODING,"");
curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt($ch, CURLOPT_POSTFIELDS,$post);
$data = curl_exec($ch);
$info = rawurldecode(var_export(curl_getinfo($ch),true));
echo "\nResponse\n$data";
echo "\ncurl_getinfo =\n$info";
?>

receiveheaders.php

<?php
header('Content-Type: text/plain; charset=UTF-8');

foreach (getallheaders() as $name => $value) {
    echo "$name: $value\n";
}
echo "\nBODY\n";
$jsn = file_get_contents('php://input');
echo "\n$jsn\n\n\n";
$data = json_decode($jsn,1);
var_export($data);
echo "\n\$_POST\n";
var_export($_POST);
echo "\n\$_FILES\n";
var_export($_FILES);
echo "\n\$_SERVER\n";
var_export($_SERVER);
?>

END OF UPDATE



Add these two headers.

$headers[] = 'Accept: application/json';
$headers[] = 'Content-Type: application/json';

Right now the error you are getting is because the request content-type is

'CONTENT_TYPE' => 'application/x-www-form-urlencoded',

If use just used the content-type header and not accept, you'd get a different error. The API manual says you cannot use curl's default Accept: */*

Sign up to request clarification or add additional context in comments.

8 Comments

Thanks for your reply @Misunderstood. But this didn`t solve the problem I still get the same error. Output is: HTTP/1.1 422 Unprocessable Entity Access-Control-Allow-Origin: * Connection: close Content-Length: 52 Content-Security-Policy: default-src 'self'; style-src 'self' 'unsafe-inline' Content-Type: application/json Server: PowerDNS/4.4.1 X-Content-Type-Options: nosniff X-Frame-Options: deny X-Permitted-Cross-Domain-Policies: none X-Xss-Protection: 1; mode=block {"error": "Creating domain 'mexamples.com.' failed"}
When i use PDNS library from Github i`m getting the same error (exonet/powerdns-php) $powerdns = new Powerdns('127.0.0.1', 'MY_KEY'); $zone = $powerdns->createZone( 'example.com', ['ns1.example.com.', 'ns2.example.com.'] );
About Content-length. When im adding $headers[] = 'Accept: application/json'; in request headers there is only $headers[] = 'Content-Type: application/json'; and i think thats why Content-Length: 52 after that i tried directly on server send curl how posted @N.Kaewkhat and it return COntent-Length: 111 but with the same error 422. Thank u @Misunderstood or spending your time on me
Trying 127.0.0.1:953... * TCP_NODELAY set * Connected to 127.0.0.1 (127.0.0.1) port 953 (#0) > POST /api/v1/servers/localhost/zones HTTP/1.1 > Host: 127.0.0.1:953 > User-Agent: curl/7.68.0 > Content-Type: application/json > X-Api-Key: MY-KEY > Accept: application/json > Content-Length: 111
Yes, tried this one too with no success :-( Anyway thank u very much for your time. I'll let know if something works out. @Misunderstood
|
-1

Can you try call the API using curl command on the maching running pDNS webserver?

curl -v \
 -H 'Content-Type: application/json' \
 -H 'X-Api-Key: MY-KEY' \
 -H 'Accept: application/json' \
 -X POST -d '{"name":"example.com.", "kind":"Native", "masters": [], "nameservers":["ns1.example.com.", "ns2.example.com."]}' \
 http://127.0.0.1:953/api/v1/servers/localhost/zones

Because I don't know your setup, so I guess that it had something relate to network. If curl request work, you should check webserver-allow-from configuration, you may try to set it to accept from all (0.0.0.0,::).

2 Comments

Tried it on server the same error HTTP/1.1 422 Unprocessable Entity Now will try to change accept from all to 0.0.0.0,::
The same error on the server with webserver-allow-from = 0.0.0.0/0 . I really don`t understand why GET works but not POST. I also have WHM(cPanel) on this server and can create DNS zones with his interface with no problem. What wrong with Powerdns?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.