a cloud service to enable your own web server (owned by you and running on your computer) to be accessible on the internet in seconds, no credit card required
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

87 lines
2.1 KiB

package main
import (
type GandiService struct {
APIUrl string
APIKey string
FreeSubdomainDomain string
type GandiDomainRecords struct {
RemoveApexNS bool `json:"remove_apex_ns"`
Items []GandiDomainRecord `json:"items"`
type GandiDomainRecord struct {
Name string `json:"rrset_name"`
Type string `json:"rrset_type"`
Values []string `json:"rrset_values"`
TTL int `json:"rrset_ttl"`
func NewGandiService(config *Config, freeSubdomainDomain string) *GandiService {
toReturn := &GandiService{
APIUrl: "https://api.gandi.net/v5",
APIKey: config.GandiAPIKey,
FreeSubdomainDomain: "greenhouseusers.com",
toReturn.ClientFactory = func() (*http.Client, *time.Time, error) {
return &http.Client{Timeout: 300 * time.Second}, nil, nil
return toReturn
func (service *GandiService) UpdateFreeSubdomains(freeSubdomains map[string][]string) error {
requestBody := GandiDomainRecords{
Items: []GandiDomainRecord{},
for subdomain, ips := range freeSubdomains {
requestBody.Items = append(requestBody.Items, GandiDomainRecord{
Name: subdomain,
Type: "A",
Values: ips,
TTL: 300,
requestBodyBytes, err := json.Marshal(requestBody)
if err != nil {
return err
endpoint := fmt.Sprintf("/livedns/domains/%s/records", service.FreeSubdomainDomain)
responseBytes, err := service.GandiHTTP("PUT", endpoint, bytes.NewBuffer(requestBodyBytes))
if err != nil {
log.Printf("Failed to update free subdomains on gandi: %s \n\nResponse was: %s\n\n", err, string(responseBytes))
return err
return nil
func (service *GandiService) GandiHTTP(method string, path string, body io.Reader) ([]byte, error) {
return service.MyHTTP200(
fmt.Sprintf("%s%s", service.APIUrl, path),
func(request *http.Request) {
request.Header.Add("Authorization", fmt.Sprintf("Apikey %s", service.APIKey))
if body != nil {
request.Header.Add("Content-Type", "application/json")